package com.hoshiicloud.saleorder.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hoshiicloud.auth.vo.TokenUsersVO;
import com.hoshiicloud.common.aop.Logable;
import com.hoshiicloud.common.api.dto.EncryptedResponseDTO;
import com.hoshiicloud.common.constant.DeleteStatusEnum;
import com.hoshiicloud.common.constant.GoodsTypeEnum;
import com.hoshiicloud.common.constant.OrderInfoServiceStatusEnum;
import com.hoshiicloud.common.constant.OrderInfoStatusEnum;
import com.hoshiicloud.common.constant.OrderMainStatusEnum;
import com.hoshiicloud.common.constant.PayOrderTypeEnum;
import com.hoshiicloud.common.constant.PayStatusEnum;
import com.hoshiicloud.common.constant.QueueConsts;
import com.hoshiicloud.common.constant.RefundStatusEnum;
import com.hoshiicloud.common.constant.ReturnGoodsStatusEnum;
import com.hoshiicloud.common.constant.SettlementEnum;
import com.hoshiicloud.common.constant.ValidStatusEnum;
import com.hoshiicloud.common.exception.CommonError;
import com.hoshiicloud.common.exception.ServiceException;
import com.hoshiicloud.common.rpc.Response;
import com.hoshiicloud.common.utils.AESUtil;
import com.hoshiicloud.common.utils.BeanUtils;
import com.hoshiicloud.common.utils.EncryptionUtil;
import com.hoshiicloud.common.utils.SignUtil;
import com.hoshiicloud.common.utils.ip.IpUtils;
import com.hoshiicloud.common.utils.token.UserInfoUtil;
import com.hoshiicloud.goods.entity.goods.GoodsSpecificationsValues;
import com.hoshiicloud.goods.entity.sku.ProductManage;
import com.hoshiicloud.goods.param.sku.ProductManageQueryParam;
import com.hoshiicloud.payment.Paylist;
import com.hoshiicloud.payment.param.RefundRequest;
import com.hoshiicloud.saleorder.dto.DispatchBillAndDetailDTO;
import com.hoshiicloud.saleorder.dto.ExtSkuDTO;
import com.hoshiicloud.saleorder.dto.GoodsAttributeDTO;
import com.hoshiicloud.saleorder.dto.OrderCalcDTO;
import com.hoshiicloud.saleorder.dto.OrderDTO;
import com.hoshiicloud.saleorder.dto.OrderGoodsDTO;
import com.hoshiicloud.saleorder.dto.OrderMultiConditionDTO;
import com.hoshiicloud.saleorder.dto.PayResultDTO;
import com.hoshiicloud.saleorder.dto.PlatStoreDTO;
import com.hoshiicloud.saleorder.dto.PoBillDTO;
import com.hoshiicloud.saleorder.dto.SkuDTO;
import com.hoshiicloud.saleorder.entity.DispatchBill;
import com.hoshiicloud.saleorder.entity.DispatchBillDetail;
import com.hoshiicloud.saleorder.entity.OrderInfo;
import com.hoshiicloud.saleorder.entity.OrderMain;
import com.hoshiicloud.saleorder.entity.Payorder;
import com.hoshiicloud.saleorder.feign.GoodsService;
import com.hoshiicloud.saleorder.feign.IdGeneratorService;
import com.hoshiicloud.saleorder.feign.MarketService;
import com.hoshiicloud.saleorder.feign.PaymentService;
import com.hoshiicloud.saleorder.feign.PlatStoreService;
import com.hoshiicloud.saleorder.feign.UserService;
import com.hoshiicloud.saleorder.mapper.OrderInfoMapper;
import com.hoshiicloud.saleorder.mapper.OrderMainMapper;
import com.hoshiicloud.saleorder.mq.RsaConfig;
import com.hoshiicloud.saleorder.param.BranchOrderQueryParam;
import com.hoshiicloud.saleorder.param.LockSkuStock;
import com.hoshiicloud.saleorder.param.OrderCalcParam;
import com.hoshiicloud.saleorder.param.OrderMainQueryParam;
import com.hoshiicloud.saleorder.param.OrderMainStatusUpdateParam;
import com.hoshiicloud.saleorder.param.OrderSubmitParam;
import com.hoshiicloud.saleorder.param.PayOrderParam;
import com.hoshiicloud.saleorder.param.PayRequestParam;
import com.hoshiicloud.saleorder.param.RefundOrderPayParam;
import com.hoshiicloud.saleorder.param.customer.CartDeleteParam;
import com.hoshiicloud.saleorder.service.OrderInfoService;
import com.hoshiicloud.saleorder.service.OrderMainService;
import com.hoshiicloud.saleorder.service.PayorderService;
import com.hoshiicloud.saleorder.service.SaleOrderService;
import com.hoshiicloud.saleorder.service.customer.ICartService;
import com.hoshiicloud.saleorder.service.sendOrder.DispatchBillDetailService;
import com.hoshiicloud.user.dto.platform.PlatDTO;
import com.hoshiicloud.user.entity.customer.Cart;
import com.hoshiicloud.user.entity.platform.Platform;
import com.hoshiicloud.user.entity.store.PlatStore;
import com.hoshiicloud.user.vo.customer.CartVO;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Base64;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 销售订单业务服务
 *
 * @author MARK
 */
@Slf4j
@Service
public class SaleOrderServiceImpl implements SaleOrderService {

    private final MarketService customerService;
    private final OrderMainService orderMainService;
    private final OrderInfoService orderInfoService;
    private final GoodsService goodsService;
    private final IdGeneratorService idGeneratorService;
    private final PaymentService paymentService;
    private final PayorderService payorderService;
    private final UserService userService;

    private final DispatchBillDetailService dispatchBillDetailService;

    private final PlatStoreService platStoreService;

    private final RabbitTemplate rabbitTemplate;

    private final OrderInfoMapper orderInfoMapper;

    private final ICartService cartService;

    private final OrderMainMapper orderMainMapper;

    private final RedisTemplate<String, Object> redisTemplate;

    private static final String ORDER_MAIN_STATUS = "orderMainStatus";

    private static final String EXCEL_REDIS_KEY = "exportExcel";

    private static final String ORDER_INFO_EXCEL_HASH_KEY = "orderInfoHashKey";

    public SaleOrderServiceImpl(
            MarketService customerService, GoodsService goodsService,
            OrderMainService orderMainService, OrderInfoService orderInfoService,
            IdGeneratorService idGeneratorService, PaymentService paymentService,
            PayorderService payorderService, UserService userService,
            DispatchBillDetailService dispatchBillDetailService,
            PlatStoreService platStoreService, RabbitTemplate rabbitTemplate,
            OrderInfoMapper orderInfoMapper, ICartService cartService,
            RedisTemplate<String, Object> redisTemplate, OrderMainMapper orderMainMapper) {
        this.customerService = customerService;
        this.goodsService = goodsService;
        this.orderMainService = orderMainService;
        this.orderInfoService = orderInfoService;
        this.idGeneratorService = idGeneratorService;
        this.paymentService = paymentService;
        this.payorderService = payorderService;
        this.userService = userService;
        this.dispatchBillDetailService = dispatchBillDetailService;
        this.platStoreService = platStoreService;
        this.rabbitTemplate = rabbitTemplate;
        this.orderInfoMapper = orderInfoMapper;
        this.cartService = cartService;
        this.redisTemplate = redisTemplate;
        this.orderMainMapper = orderMainMapper;
    }

    /**
     * 计算订单
     *
     * @param param OrderCalcParam
     * @return OrderCalcDTO
     * @see #setCardQueryParam(QueryWrapper, List) 设置购物车查询参数
     * @see #calcAndSetOrderCalcVo(BigDecimal) 设置计算订单DTO
     */
    @Override
    public OrderCalcDTO calcOrder(OrderCalcParam param) {

        return Optional.ofNullable(param).map(orderCalcParam -> {
            // 商品总金额
            BigDecimal goodsAmount = BigDecimal.ZERO;

            List<Long> cartIds = param.getCartIds();
            String key = param.toString();
            Response<List<CartVO>> response = queryCard(key, cartIds);

            if (null != response) {
                List<CartVO> cartVos = response.getData();
                if (CollectionUtils.isNotEmpty(cartVos)) {
                    for (CartVO cartVO : cartVos) {
                        /*
                         * 这里并不能直接使用流遍历, 原因: 猜想是因为多线程
                         * 暂时获取购物车价格， 购物车价格 * 商品数量
                         * TODO 后续根据业务需求再细化，若sku价格发生变化
                         */
                        goodsAmount = goodsAmount.add(cartVO.getGoodsPrice())
                                .multiply(BigDecimal.valueOf(cartVO.getGoodsQuantity()));
                    }
                }
            }

            // 设置计算订单DTO并返回
            return calcAndSetOrderCalcVo(goodsAmount);

        }).orElseThrow(() -> new ServiceException("计算失败, 参数为空"));
    }


    /**
     * 设置计算订单DTO
     *
     * @param goodsAmount goodsAmount
     * @return OrderCalcDTO
     */
    private OrderCalcDTO calcAndSetOrderCalcVo(BigDecimal goodsAmount) {
        // 运费
        BigDecimal shippingFee = BigDecimal.ZERO;
        // 优惠金额
        BigDecimal coupAmount = BigDecimal.ZERO;
        // 应付金额
        BigDecimal payableAmount = BigDecimal.ZERO;
        // 计算应付金额
        payableAmount = goodsAmount.add(shippingFee).subtract(coupAmount);

        return OrderCalcDTO.builder()
                .goodsAmount(goodsAmount)
                .shippingFee(shippingFee)
                .coupAmount(coupAmount)
                .payableAmount(payableAmount)
                .build();
    }

    /**
     * 提交订单业务逻辑处理
     *
     * @param param param
     * @return Response
     * @see #setIdType(Integer, Set) 将Id转换为Long类型
     * @see #queryCard(String, List) 根据RedisKey和购物车Id集合查询购物车信息
     * @see #responseIfNotAbsent(Response, OrderSubmitParam, Long, Long) 如果购物车是存在的就生成子订单,主订单
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Response submitOrder(OrderSubmitParam param) {
        // 提交订单类型(1立即购买 0购物车购买)
        Integer submitType = param.getSubmitType();
        if (1 == submitType) {
            // 购买数量
            Long buyNum = param.getBuyNum();
            // 判断是否为立即购买提交订单方式
            if (0 >= buyNum) {
                log.error("提交订单失败, 立即购买数量不能为空");
                throw new ServiceException("提交订单失败，立即购买数量不能为空");
            }
        }
        // 获取两个Id
        Integer generateIdNum = 2;
        Set<String> idStrSet = idGeneratorService.queryGeneratorIds(generateIdNum);
        Set<Long> orderMainIdSet = this.setIdType(generateIdNum, idStrSet);

        Iterator<Long> oneIterator = orderMainIdSet.iterator();

        // // 获取生成的第一个Id, 成为主订单Id
        Long orderMainId = oneIterator.next();
        // orderNo
        Long orderNo = oneIterator.next();
        List<Long> cartIds = param.getCartIds();

        // 根据购物车id查询购物车
        String key = param.toString();
        Response<List<CartVO>> response = this.queryCard(key, cartIds);

        if (null != response) {

            List<CartVO> cartVos = response.getData();

            if (CollectionUtils.isNotEmpty(cartVos)) {
                // 如果购物车是存在的
                this.responseIfNotAbsent(response, param, orderMainId, orderNo);

                Map<String, Object> map = new HashMap<>(16);
                map.put("orderId", orderMainId);

                return Response.success("提交订单成功", map);
            } else {
                return Response.failed("提交订单失败，获取商品信息异常");
            }
        } else {
            log.error("提交订单失败，获取商品信息异常");
            throw new ServiceException("提交订单失败，获取商品信息异常");
        }
    }

    /**
     * 如果有查询到购物车信息
     *
     * @param response response
     * @param param    param
     * @see #querySkuStockBySkuIds(List) 通过购物车集合, 拿到库存
     * @see #getStockToSkuVoMap(Response) 拿到库存的Map
     * @see #setIdType(Integer, Set) 将Id转换为Long类型
     * @see #generateOrderInfo(OrderSubmitParam, Long, Long, List, Map, Iterator, List, List) 生成子订单, 生成主订单也在这个方法中
     */
    private void responseIfNotAbsent(Response<List<CartVO>> response, OrderSubmitParam param,
            Long orderMainId,
            Long orderNo) {

        List<CartVO> cartVos = response.getData();
        // 调用goods服务 根据skuId, 查询库存信息
        Response<Map<Long, SkuDTO>> skuStockByIdsResponse = this.querySkuStockBySkuIds(cartVos);

        // 将库存放入一个新的Map中
        Map<Long, SkuDTO> skuVoMap = this.getStockToSkuVoMap(skuStockByIdsResponse);

        // 一个购物车或者一个订单中的商品数量
        int goodsNum = cartVos.size();
        if (goodsNum > 100) {
            throw new ServiceException("商品数量不能超过100");
        }
        Set<String> idStrSet = idGeneratorService.queryGeneratorIds(goodsNum);
        Set<Long> orderInfoIdSet = this.setIdType(goodsNum, idStrSet);
        Iterator<Long> twoIterator = orderInfoIdSet.iterator();

        // 避免出现多线程变量不可用的情况, 用forEach
        // 子订单总金额

        List<OrderInfo> orderInfoList = new ArrayList<>(10);
        List<LockSkuStock> lockSkuStockList = new ArrayList<>(10);

        // 生成子订单, 在生成主单后生成
        this.generateOrderInfo(param, orderMainId, orderNo, cartVos, skuVoMap, twoIterator,
                orderInfoList, lockSkuStockList);

        // 批量保存子订单信息
        orderInfoService.saveBatch(orderInfoList, 1000);

        // 冻结Sku库存
        if (CollectionUtils.isNotEmpty(lockSkuStockList)) {
            goodsService.lockSkuStock(lockSkuStockList);
        }

        List<Long> cartIds = param.getCartIds();
        // 清除购物车记录
        if (param.getSubmitType() == 1) {
            // 立即购买提交订单方式 清除购物车
            if (CollectionUtils.isNotEmpty(cartIds)) {
                CartDeleteParam deleteParam = CartDeleteParam.builder()
                        .id(param.getCartIds().get(0))
                        .goodsQuantity(param.getBuyNum())
                        .build();
                cartService.deleteDataByNumber(deleteParam);
            }
        } else {
            // 购物车提交订单 方式清除购物车
            cartService.deleteDataByIds(cartIds);
        }
    }

    /**
     * 生成子订单
     *
     * @param param            param
     * @param orderMainId      orderMainId
     * @param orderNo          orderNo
     * @param cartVos          cartVos
     * @param skuVoMap         skuVoMap
     * @param twoIterator      twoIterator
     * @param orderInfoList    orderInfoList
     * @param lockSkuStockList lockSkuStockList
     * @see #setOrderInfoMessage(OrderSubmitParam, Long, Long, String, SkuDTO, BigDecimal, BigDecimal, BigDecimal, CartVO, Iterator, List,
     * List) 生成子订单实体
     * @see #setOrderMainMessage(OrderSubmitParam, OrderInfo, Long, Long, BigDecimal, BigDecimal, BigDecimal) 生成主订单实体
     */
    private void generateOrderInfo(OrderSubmitParam param,
            Long orderMainId, Long orderNo,
            List<CartVO> cartVos, Map<Long, SkuDTO> skuVoMap,
            Iterator<Long> twoIterator,
            List<OrderInfo> orderInfoList, List<LockSkuStock> lockSkuStockList) {

        BigDecimal goodsTotalAmount = BigDecimal.ZERO;
        for (int i = 0; i < cartVos.size(); i++) {
            int countNum = i + 1;
            CartVO cartVo = cartVos.get(i);
            // 得到基础Sku和扩展Spu DTO
            SkuDTO skuDTO = skuVoMap.get(cartVo.getSkuId());

            Integer goodsStatus = 3;
            if (goodsStatus.equals(skuDTO.getStatus())) {
                throw new ServiceException("该商品已下架无法生成订单");
            }

            // 若允许负库存为1则无需检验,否则检验租户分配的商品数量是否足够
            // 检验商品可用数量
            BigDecimal buyNum;
            if (param.getSubmitType() == 1) {
                //立即购买提交订单
                buyNum = BigDecimal.valueOf(param.getBuyNum());
            } else {
                //购物车购买提交订单
                buyNum = BigDecimal.valueOf(cartVo.getGoodsQuantity());
            }
            // 判断当前店铺是不是分销店铺，如果十分销店铺，这里拿总店的库存 add by yangcheng
            Response<PlatStore> storeResponse = userService.queryById(skuDTO.getStoreId());
            if (storeResponse.getData().getIsDistributor().equals(1)) {
                ProductManageQueryParam productManageQueryParam = new ProductManageQueryParam();
                productManageQueryParam.setStoreId(storeResponse.getData().getParentId());
                productManageQueryParam.setBaseSkuId(skuDTO.getSkuId());
                Response<List<ProductManage>> manageResponse = goodsService.listProductManage(productManageQueryParam);
                skuDTO.setQuantity(manageResponse.getData().get(0).getQuantity());
                skuDTO.setFreezes(manageResponse.getData().get(0).getFreezes());
            }
            // 根据冻结数量
            BigDecimal freezes = skuDTO.getFreezes();
            BigDecimal availableNum = Optional.ofNullable(freezes)
                    // 库存DTO中的冻结数量 - 已有的库存数量 如果冻结的数量这个变量不为null
                    .map(stockFreezes -> skuDTO.getQuantity().subtract(stockFreezes))
                    // 库存DTO中的冻结数量
                    .orElseGet(skuDTO::getQuantity);

            // 如果库存数量 - 购买数量小于0抛出异常
            if (0 > availableNum.subtract(buyNum).doubleValue()) {
                throw new ServiceException(skuDTO.getSpuTitle() + "商品库存不足");
            }

            //子订单编号
            String detailOrderInfoNo = null;
            if (countNum < 10) {
                // 补零
                detailOrderInfoNo = String.format("%s%d%d", orderNo, 0, countNum);
            }
            if (countNum > 10) {
                // 商品数量大于10 时不补零
                detailOrderInfoNo = String.format("%s%d", orderNo, countNum);
            }

            // 主订单商品总金额
            BigDecimal goodsAmount = BigDecimal.ZERO;
            // setScale 必须使用return形式才能赋值
            goodsAmount = (cartVo.getGoodsPrice().multiply(buyNum))
                    .setScale(2, RoundingMode.HALF_DOWN);

            goodsTotalAmount = goodsTotalAmount.add(goodsAmount);
            // 应付金额
            BigDecimal payableAmount = goodsAmount;

            // 生成子订单实体
            this.setOrderInfoMessage(param, orderMainId, orderNo, detailOrderInfoNo, skuDTO,
                    goodsAmount,
                    payableAmount, buyNum,
                    cartVo,
                    twoIterator, orderInfoList, lockSkuStockList);
        }

        OrderInfo firstOrderInfo = orderInfoList.get(0);
        //运费
        BigDecimal shippingFee = BigDecimal.ZERO;
        //优惠金额
        BigDecimal coupAmount = BigDecimal.ZERO;
        BigDecimal payableTotalAmount = goodsTotalAmount.add(shippingFee).subtract(coupAmount)
                .setScale(2, RoundingMode.HALF_DOWN);

        // 生成主订单
        OrderMain orderMain = this.setOrderMainMessage(param, firstOrderInfo, orderMainId, orderNo,
                goodsTotalAmount,
                payableTotalAmount,
                coupAmount);

        // 保存主订单信息
        orderMainService.save(orderMain);
    }

    /**
     * 生成主订单信息
     *
     * @param param              param
     * @param firstOrderInfo     firstOrderInfo
     * @param orderMainId        orderMainId
     * @param orderNo            orderNo
     * @param goodsTotalAmount   goodsTotalAmount
     * @param payableTotalAmount payableTotalAmount
     * @param coupAmount         coupAmount
     * @return OrderMain
     */
    private OrderMain setOrderMainMessage(OrderSubmitParam param, OrderInfo firstOrderInfo,
            Long orderMainId,
            Long orderNo,
            BigDecimal goodsTotalAmount, BigDecimal payableTotalAmount, BigDecimal coupAmount) {
        //金币积分数
        Long points = 0L;
        OrderMain orderMain = OrderMain.builder()
                .id(orderMainId)
                // TODO 要转换成Long类型, 这里应该是MainNo, 感觉错了
                .mainNo(orderNo.toString())
                // 订单类别   1-实物订单  2-服务订单,
                .type(param.getType())
                // 订单渠道  1-线上 2-线下,
                .channel(param.getChannel())
                // 订单来源'1（APP_ANDROID ），2（APP_IOS），3（WEB_MOBILE），4（WEB_PC），5（SMALL_ROUTINE_ANDROID），6（SMALL_ROUTINE_IOS)
                .source(param.getSource())
                // 支付方式名称
                .payName("")
                // 结算方式 1: 一次结清, 2 分期付款
                .settlement(SettlementEnum.ONE_PAYMENT.getCode())
                // 租户Id
                .companyId(firstOrderInfo.getCompanyId())
                // 平台ID
                .platformId(firstOrderInfo.getPlatformId())
                // 店铺ID
                .storeId(firstOrderInfo.getStoreId())
                // 会员ID
                .memberId(param.getUserId())
                // 收货人姓名
                .consignee(param.getConsignee())
                // 收货人的国家region
                .country(param.getCountry())
                // 国家名称
                .countryName(param.getCountryName())
                // 收货人的省份
                .province(param.getProvince())
                // 省份名称
                .provinceName(param.getProvinceName())
                // 收货人的城市
                .city(param.getCity())
                // 收货人的城市名称
                .cityName(param.getCityName())
                // 收货人的地区
                .district(param.getDistrict())
                // 收货人地区名称
                .districtName(param.getDistrictName())
                // 收货人的详细地址
                .address(param.getAddress())
                // 收货人的邮编
                .zipCode(param.getZipCode())
                // 收货人的电话
                .telephone(param.getTelephone())
                // 收货人的手机
                .mobile(param.getMobile())
                // 收货人的邮箱
                .email(param.getEmail())
                // 订单类型
                .shippingId(param.getShippingId())
                // 收货人的最佳送货时间
                .bestTime(param.getBestTime())
                // 收货人的地址的标志性建筑
                .signBuilding(param.getSignBuilding())
                // 订单附言, 由用户提交订单前填写
                .postscript(param.getPostscript())
                // 实付款 TODO 注意金额是否正确
                .goodsAmount(goodsTotalAmount)
                // 商品总金额
                .amount(payableTotalAmount)
                // 实付款
                .orderAmount(payableTotalAmount)
                // 优惠券抵扣金额
                .benefitsAmount(coupAmount)
                // 余额抵扣
                .balanceAmount(BigDecimal.ZERO)
                // 金币抵扣金额
                .coinsAmount(BigDecimal.ZERO)
                // 物流运费
                .shippingFee(BigDecimal.ZERO)
                // 使用积分或金币数
                .points(points)
                .backAmount(BigDecimal.ZERO)
                // 订单状态 待付款
                .orderStatus(OrderMainStatusEnum.WAIT_PAYING.getCode())
                // 发货状态 待发货
                // .shippingStatus(ShippingStatusEnum.UN_SHIPPED.getCode())
                // 付款状态. 未付款
                .payStatus(PayStatusEnum.UN_PAID.getCode())
                .serviceStatus(OrderInfoServiceStatusEnum.WITHOUT_AFTER_SALE.getCode())
                // 设置交付时间（针对好获拼拼，用来存储自提时间）add by yangcheng
                .deliveryTime(firstOrderInfo.getDeliveryTime())
                .build();

        Object pickUpCodeObject = redisTemplate.opsForValue().get("pickUpCode:" + LocalDate.now());
        if (pickUpCodeObject == null) {
            redisTemplate.opsForValue().set("pickUpCode:" + LocalDate.now(), 1);
            orderMain.setPickUpCode("1");
        } else {
            int pickUpCode = Integer.parseInt(pickUpCodeObject.toString());
            pickUpCode = pickUpCode + 1;
            redisTemplate.opsForValue().set("pickUpCode:" + LocalDate.now(), pickUpCode);
            orderMain.setPickUpCode(pickUpCode + "");
        }
        return orderMain;
    }

    /**
     * 设置OrderInfo信息
     *
     * @param param             param
     * @param orderMainId       orderMainId
     * @param orderNo           orderNo
     * @param detailOrderInfoNo detailOrderInfoNo
     * @param skuDTO            skuDTO
     * @param goodsAmount       goodsAmount
     * @param payableAmount     payableAmount
     * @param buyNum            buyNum
     * @param cartVo            cartVo
     * @param twoIterator       twoIterator
     * @param orderInfoList     orderInfoList
     * @param lockSkuStockList  lockSkuStockList
     */
    private void setOrderInfoMessage(OrderSubmitParam param, Long orderMainId,
            Long orderNo, String detailOrderInfoNo, SkuDTO skuDTO, BigDecimal goodsAmount,
            BigDecimal payableAmount, BigDecimal buyNum,
            CartVO cartVo,
            Iterator<Long> twoIterator, List<OrderInfo> orderInfoList,
            List<LockSkuStock> lockSkuStockList) {
        OrderInfo orderInfo = OrderInfo.builder()
                // 子订单Id
                .id(twoIterator.next())
                // 主订单id
                .mainId(orderMainId)
                // 用户Id
                .memberId(param.getUserId())
                // TODO 要转换成Long类型, 这里应该是MainNo, 感觉错了
                .mainNo(orderNo.toString())
                // 订单编号 TODO 要转换成Long类型
                .orderNo(detailOrderInfoNo)
                // 删除标识
                .deleted(DeleteStatusEnum.UN_DELETED.getCode())
                // 公司Id
                .companyId(skuDTO.getCompanyId())
                // 平台Id
                .platformId(cartVo.getPlatformId())
                // 商店Id
                .storeId(cartVo.getStoreId())
                .skuId(cartVo.getSkuId())
                .skuName(cartVo.getSkuTitle())
                // 商品数量
                .amount(goodsAmount)
                // SPUId
                .spuId(cartVo.getSpuId())
                // Spu编号
                .spuNo(skuDTO.getSpuNo())
                .spuName(cartVo.getSpuTitle())
                // 订单金额
                .orderAmount(payableAmount)
                .coinsAmount(BigDecimal.ZERO)
                .balanceAmount(BigDecimal.ZERO)
                .benefitsAmount(BigDecimal.ZERO)
                // 使用积分
                .points(0L)
                // 金币代扣
                .quantity(buyNum.longValue())
                // 商品售价
                .saleUnitPrice(cartVo.getGoodsPrice())
                // 商品最终价
                .unitPrice(cartVo.getGoodsPrice())
                // 是否跨境 1 是 0否
                .overseas(ValidStatusEnum.INVALID.getCode())
                // 是否自营 1 是 0 否
                .own(ValidStatusEnum.VALID.getCode())
                .createdTime(LocalDateTime.now())
                // 订单状态 等待买家付款
                .orderStatus(OrderInfoStatusEnum.WAIT_PAYING.getCode())
                // 发货状态 未发货
//                .shippingStatus(ShippingStatusEnum.UN_SHIPPED.getCode())
                // 支付状态 未付款
                .payStatus(PayStatusEnum.UN_PAID.getCode())
                // 售后状态 未售后
                .serviceStatus(OrderInfoServiceStatusEnum.WITHOUT_AFTER_SALE.getCode())
                .refundStatus(RefundStatusEnum.NO_NEED_REFUND.getCode())
                .returnGoodsStatus(ReturnGoodsStatusEnum.NO_NEED_TO_RETURN.getCode())
                .build();

        // 根据购物车
        LockSkuStock lockSkuStock = LockSkuStock.builder()
                .baseSkuid(skuDTO.getSkuId())
                .extSkuid(cartVo.getSkuId())
                .companyid(skuDTO.getCompanyId())
                .platformid(cartVo.getPlatformId())
                .storeid(cartVo.getStoreId())
                .lockNum(buyNum.longValue())
                .build();
        // 设置交付时间（针对好获拼拼，用来存储自提时间）add by yangcheng
        if (skuDTO.getReceiptInterval().equals(0) && null != skuDTO.getReceiptDate()) {
            orderInfo.setDeliveryTime(skuDTO.getReceiptDate());
        } else {
            // 判断是否22:00后下单，22:00后下单，提货日期多加一天
            LocalDateTime endTime = LocalDateTime.now().withHour(22).withMinute(0).withSecond(0);
            if (LocalDateTime.now().isAfter(endTime)) {
                orderInfo.setDeliveryTime(LocalDateTime.now().plusDays(skuDTO.getReceiptInterval() + 1));
            } else {
                orderInfo.setDeliveryTime(LocalDateTime.now().plusDays(skuDTO.getReceiptInterval()));
            }
        }
        orderInfoList.add(orderInfo);
        lockSkuStockList.add(lockSkuStock);
        if (cartVo.getSpuExtendSpec() != null) {
            // 规格json对象不能为空
            orderInfo.setSpuExtendSpec(JSON.toJSONString(cartVo.getSpuExtendSpec()));
        }
        if (CollectionUtils.isEmpty(orderInfoList)) {
            throw new ServiceException("提交订单失败，子订单为空");
        }

    }

    /**
     * 获取商品库存转换成SkuVoMap
     *
     * @param skuStockByIdsResponse skuStockByIdsResponse
     */
    private Map<Long, SkuDTO> getStockToSkuVoMap(Response<Map<Long, SkuDTO>> skuStockByIdsResponse) {
        if (null != skuStockByIdsResponse) {
            Map<Long, SkuDTO> data = skuStockByIdsResponse.getData();
            if (CollectionUtils.isNotEmpty(data)) {
                return data;
            } else {
                throw new ServiceException("获取商品库存失败");
            }
        }
        throw new ServiceException("调用商品库存失败");
    }

    /**
     * 根据购物车中的skuId 查询库存
     *
     * @param cartVos cartVos
     * @return Response
     * <p>
     * update by 杨成 修改库存获取方式：库存这里不能直接去找对应分店，逻辑为如果分店为为分销类型，默认去找总店对应的库存
     */
    private Response<Map<Long, SkuDTO>> querySkuStockBySkuIds(List<CartVO> cartVos) {
        LinkedList<Long> skuIdList = new LinkedList<>();
        cartVos.forEach(cartVo -> skuIdList.add(cartVo.getSkuId()));
        return goodsService.getSkuStockByIds(skuIdList);
    }

    /**
     * 根据购物车中的skuId 查询库存
     *
     * @param cartVos cartVos
     * @return Response
     */
    private Response<Map<Long, SkuDTO>> queryHeadOfficeSkuStockByIds(List<CartVO> cartVos) {

        List<Long> cartVoIdList = cartVos.stream()
                .map(CartVO::getRecId)
                .collect(Collectors.toList());
        return goodsService.queryHeadOfficeSkuStockByIds(cartVoIdList);
    }


    /**
     * 查询购物车
     *
     * @param key     缓存key
     * @param cartIds 购物车Id
     * @return Response
     * @see #setCardQueryParam(QueryWrapper, List) 设置购物车查询参数
     */
    private Response<List<CartVO>> queryCard(String key, List<Long> cartIds) {
        QueryWrapper<Cart> cartQueryWrapper = new QueryWrapper<>();
        setCardQueryParam(cartQueryWrapper, cartIds);
        return cartService.getList(cartQueryWrapper, key);
    }

    /**
     * 设置购物车查询参数
     *
     * @param cartQueryWrapper cartQueryWrapper
     * @param cartIds          购物车id
     */
    private void setCardQueryParam(QueryWrapper<Cart> cartQueryWrapper, List<Long> cartIds) {
        cartQueryWrapper.lambda().in(Cart::getRecId, cartIds)
                .eq(Cart::getStatus, ValidStatusEnum.VALID.getCode())
                .eq(Cart::getDeleted, DeleteStatusEnum.UN_DELETED.getCode());
    }

    /**
     * 设置Id类型
     *
     * @param generateIdNum 生成的id个数
     * @param idStrSet      字符串Id集合
     * @return 转换的结果
     */
    private Set<Long> setIdType(Integer generateIdNum, Set<String> idStrSet) {

        if (!generateIdNum.equals(idStrSet.size())) {
            throw new ServiceException("提交订单失败，生成订单主键数量有误");
        }

        // map是转换, 形成一个新的集合, forEach是遍历, 同一个集合
        return idStrSet.stream().map(idStr -> {
            if (StrUtil.isBlank(idStr)) {
                throw new ServiceException("提交订单失败，生成订单主键失败");
            }
            return Long.valueOf(idStr);
        }).collect(Collectors.toSet());
    }

    /**
     * 根据主订单id 支付订单
     *
     * @param param param
     * @return PayResultDTO
     */
    @Override
    public PayResultDTO payOrder(PayOrderParam param) {
        // 主订单
        OrderMain orderMain = orderMainService.getById(param.getOrderId());
        // 找不到主单
        if (null == orderMain) {
            throw new ServiceException("订单支付异常，无法找到订单");
        }

        BigDecimal amountByOrderMain = orderMain.getAmount();
        BigDecimal actualAmount = amountByOrderMain.setScale(2, RoundingMode.HALF_DOWN);
        BigDecimal amount = amountByOrderMain.multiply(BigDecimal.valueOf(100));

        int payOrderIdNum = 2;
        Set<String> idStrSet = idGeneratorService.queryGeneratorIds(payOrderIdNum);

        Set<Long> payOrderIdSet = setIdType(payOrderIdNum, idStrSet);

        Iterator<Long> idIterator = payOrderIdSet.iterator();
        Long payOrderId = idIterator.next();

        //判断主订单上是否有联合订单号,找到对应的payorder
        Payorder payorder = null;
        if (orderMain.getUnionId() != null) {
            QueryWrapper<Payorder> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(Payorder::getPayOrderNo, orderMain.getUnionId().toString());
            try {
                payorder = payorderService.getOne(queryWrapper);
                if (payorder.getStatus().equals(1)) {
                    throw new ServiceException("订单已支付,请勿重复支付");
                }
            } catch (ServiceException e) {
                throw e;
            } catch (Exception e) {
                throw new ServiceException("有重复的联合订单号, 请排查");
            }
        }
        if (payorder != null) {
            payOrderId = payorder.getId();
        }
        PayRequestParam payRequestParam = PayRequestParam.builder()
                .amount(amount.intValue())
                // 支付类型 weixin 微信小程序支付 alipay支付宝支付
                .channel(param.getChannel())
                // 商户号用订单的平台id
                .merId(orderMain.getPlatformId())
                // 商户订单号
                .merOrderId(String.valueOf(payOrderId))
                // 商品类型 :0-虚拟类商品,1-实物类商品
                .goodsType(String.valueOf(GoodsTypeEnum.FACTUAL_GOODS.getCode()))
                // 订单名称
                .orderName("好货严选")
                // 客户端支付-成功后地址
                .returnUrl(param.getReturnUrl())
                // //支付模式,暂时支持PAGE,WAP,WEBAPP(微信小程序/H5支付),NATIVEAPP(原生支付)
                .payMode(param.getPayMode())
                .userId(String.valueOf(orderMain.getMemberId()))
                .userIP("127.0.0.1")
                .userThirdId(param.getOpenId()).build();

        return generatePaySignature(orderMain, payRequestParam, payOrderId, actualAmount, param.getOrderId(),
                idIterator);
    }

    /**
     * 生成支付签名
     *
     * @param payRequestParam payRequestParam
     */
    private PayResultDTO generatePaySignature(OrderMain orderMain, PayRequestParam payRequestParam,
            Long payOrderId,
            BigDecimal actualAmount, Long orderId, Iterator<Long> idIterator) {
        TreeMap<String, String> map = new TreeMap<>();
        map.put("userId", payRequestParam.getUserId());
//        map.put("amount", String.valueOf(payRequestParam.getAmount()));//支付金额 测试1.01元
        map.put("amount", String.valueOf(payRequestParam.getAmount()));//支付金额 测试1.01元
        map.put("channel", payRequestParam.getChannel());//支付类型 weixin 微信小程序支付 alipay支付宝支付
        map.put("goodsType", payRequestParam.getGoodsType());//商品主类型 :0-虚拟类商品,1-实物类商品
        map.put("merId", String.valueOf(payRequestParam.getMerId()));//商户号
        map.put("merOrderId", String.valueOf(payOrderId));//支付订单id
        map.put("orderName", payRequestParam.getOrderName());//订单名称
//        map.put("payMode", "WEBAPP");//支付模式,暂时支持PAGE,WAP,WEBAPP,NATIVEAPP
        map.put("payMode", payRequestParam.getPayMode());//支付模式,暂时支持PAGE,WAP,WEBAPP,NATIVEAPP 测试模式
        map.put("userIP", "127.0.0.1");//用户id
        map.put("userThirdId", payRequestParam.getUserThirdId());
        if (StringUtils.isNotEmpty(payRequestParam.getReturnUrl())) {
            map.put("returnUrl", payRequestParam.getReturnUrl());
        }
        log.info("订单支付" + payRequestParam.toString());
        log.info("订单支付参数" + map.toString());
        String sign = SignUtil.sign(map, SignUtil.SIGN_SECRECT_KEY);
        payRequestParam.setSign(sign);

        Response<PayResultDTO> response = paymentService.order(payRequestParam);
        if (null != response) {
            if (response.isSuccess()) {
                PayResultDTO payResultDTO = response.getData();
                generatePayOrder(orderMain, payOrderId, payResultDTO, actualAmount, orderId,
                        idIterator);
                return payResultDTO;
            } else {
                throw new ServiceException("支付失败, 调用统一下单接口异常" + response.getMsg());
            }
        } else {
            throw new ServiceException("支付失败，调用统一下单接口异常");
        }
    }


    /**
     * 生成支付订单
     *
     * @param payOrderId
     * @param payResultDTO
     */
    @Async
    public void generatePayOrder(OrderMain orderMain, Long payOrderId, PayResultDTO payResultDTO,
            BigDecimal actualAmount, Long orderId, Iterator<Long> idIterator) {
        Payorder payOrder = Payorder.builder()
                .payListId(Long.valueOf(payResultDTO.getOrderId()))
                .build();
        if (null == orderMain.getUnionId()) {
            payOrder.setCreatedBy("admin")
                    .setId(payOrderId)
                    // 支付流水id
                    .setPayListId(Long.valueOf(payResultDTO.getOrderId()))
                    .setPayAmount(actualAmount)
                    .setPayOrderNo(idIterator.next().toString())
                    .setStatus(PayStatusEnum.UN_PAID.getCode())
                    .setType(PayOrderTypeEnum.CONSUME.getCode())
                    .setUserId(orderMain.getMemberId());

            // 生成联合订单号Id
            String unionIdStr = idGeneratorService.queryGeneratorId();
            Long unionId = Long.parseLong(unionIdStr);

            //修改支付订单id至订单至子订单表
            List<OrderInfo> orderInfoList = orderInfoService.listByOrderId(orderId);

            for (OrderInfo orderInfo : orderInfoList) {
                // 支付流水id
                orderInfo.setPayOrderId(payOrderId)
                        // 未付款
                        .setPayStatus(PayStatusEnum.UN_PAID.getCode())
                        .setServiceStatus(OrderInfoServiceStatusEnum.WITHOUT_AFTER_SALE.getCode());
            }

            // 联合订单号
            payOrder.setPayOrderNo(unionIdStr);
            payorderService.save(payOrder);
            orderMain.setUnionId(unionId);
            orderMainService.updateById(orderMain);
            orderInfoService.updateByList(orderInfoList);
        } else {
            log.info("联合订单号:" + orderMain.getUnionId());
            QueryWrapper<Payorder> payorderQueryWrapper = new QueryWrapper<>();
            payorderQueryWrapper.lambda().eq(Payorder::getPayOrderNo, orderMain.getUnionId().toString());
            List<Payorder> payorderList = payorderService.list(payorderQueryWrapper);
            if (CollectionUtils.isNotEmpty(payorderList)) {
                if (payorderList.size() == 1) {
                    payOrder.setId(payorderList.get(0).getId()).updateById();
                }
                if (payorderList.size() != 1) {
                    throw new ServiceException("有重复的联合订单号, 请排查");
                }
            } else {
                throw new ServiceException("生成联合订单Id出现错误");
            }
        }

    }

    /**
     * 取消订单
     *
     * @param orderId orderId
     * @return boolean
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean cancelOrder(Long orderId) {
        if (orderId != null) {
            OrderMain orderMain = orderMainService.getById(orderId);
            if (orderMain != null) {
                //已经付款的无法取消订单
                if (PayStatusEnum.HAS_PAID.getCode() == orderMain.getPayStatus()) {
                    throw new ServiceException(CommonError.error("订单已付款，无法进行取消操作"));
                }
                //已取消
                orderMain.setOrderStatus(OrderMainStatusEnum.ORDER_CANCELLATION.getCode())
                        // 取消时间
                        .setCancelledTime(LocalDateTime.now())
                        // //更新时间
                        .setUpdatedTime(LocalDateTime.now())
                        .setUpdatedBy("admin")
                        .updateById();
                // orderMainService.updateById(orderMain);

                //修改子订单表
                List<OrderInfo> orderInfoList = orderInfoService.listByOrderId(orderId);

                if (CollectionUtils.isNotEmpty(orderInfoList)) {

                    List<LockSkuStock> lockSkuStocks = new ArrayList<>(10);

                    orderInfoList.forEach(orderInfo -> {
                        //已取消
                        orderInfo.setOrderStatus(OrderInfoStatusEnum.ORDER_CANCELLATION.getCode())
                                //取消时间
                                .setCancelledTime(LocalDateTime.now())
                                //更新时间
                                .setUpdatedTime(LocalDateTime.now())
                                .setUpdatedBy("admin");
                        LockSkuStock lockSkuStock = LockSkuStock.builder()
                                .extSkuid(orderInfo.getSkuId())
                                .companyid(orderInfo.getCompanyId())
                                .platformid(orderInfo.getPlatformId())
                                .storeid(orderInfo.getStoreId())
                                .lockNum(orderInfo.getQuantity())
                                .build();
                        lockSkuStocks.add(lockSkuStock);
                    });

                    orderInfoService.updateBatchById(orderInfoList);

                    //解冻商品sku库存
                    goodsService.unLockSkuStock(lockSkuStocks);
                }

            }
            return true;
        } else {
            return false;
        }
    }

    /**
     * 批量取消订单
     *
     * @param orderIds orderIds
     * @return Response
     */
    @Override
    public boolean batchCancelOrders(List<Long> orderIds) {
        boolean state;
        try {
            List<OrderMain> updateOrderMainList = new ArrayList<>();
            List<OrderInfo> updateOrderInfoList = new ArrayList<>();
            for (Long orderId : orderIds) {
                // 根据主订单id查询
                OrderMain orderMain = orderMainService.getById(orderId);
                QueryWrapper<OrderInfo> queryWrapper = new QueryWrapper<>();
                queryWrapper.lambda().eq(OrderInfo::getMainId, orderId);
                List<OrderInfo> orderInfoList = orderInfoService.listByQueryWrapper(queryWrapper);
                if (CollectionUtils.isNotEmpty(orderInfoList)) {
                    orderInfoList.forEach(orderInfo -> {
                        //修改子订单状态
                        OrderInfo updateOrderInfo = OrderInfo.builder()
                                .id(orderInfo.getId())
                                .orderStatus(OrderInfoStatusEnum.ORDER_CANCELLATION.getCode())
                                .updatedTime(LocalDateTime.now())
                                .build();

                        updateOrderInfoList.add(updateOrderInfo);
                    });
                    //修改主订单状态及时间
                    orderMain.setOrderStatus(OrderMainStatusEnum.ORDER_CANCELLATION.getCode())
                            .setUpdatedTime(LocalDateTime.now());
                    updateOrderMainList.add(orderMain);
                }
            }
            boolean updateMainOrderState = orderInfoService.updateByList(updateOrderInfoList);
            boolean updateInfoOrderState = orderMainService.updateByList(updateOrderMainList);
            // 解冻相应的库存
            LinkedList<Long> skuIdList = new LinkedList<>();
            updateOrderInfoList.forEach(item -> skuIdList.add(item.getSkuId()));
            // 以skuId分組，统计每个sku购买数量
            Map<Long, List<OrderInfo>> groupMap = updateOrderInfoList.stream().collect(Collectors.groupingBy(OrderInfo::getSkuId));
            Map<Long, Long> groupCountMap = new HashMap<>();
            groupMap.forEach((key, orderInfoList) -> {
                Long temp = orderInfoList.stream().mapToLong(OrderInfo::getQuantity).sum();
                groupCountMap.put(key, temp);
            });
            // for (Long key : groupMap.keySet()) {
            //     Long temp = 0L;
            //     for (OrderInfo orderInfo : groupMap.get(key)) {
            //         temp += orderInfo.getQuantity();
            //     }
            //     groupCountMap.put(key, temp);
            // }
            // sku库存
            List<LockSkuStock> lockSkuStocks = new ArrayList<>();
            Response<Map<Long, SkuDTO>> skuStocks = goodsService.getSkuStockByIds(skuIdList);
            if (null != skuStocks && skuStocks.getCode() == 200 && null != skuStocks.getData()) {
                skuStocks.getData().keySet().forEach(item -> {
                    LockSkuStock lockSkuStock = new LockSkuStock();
                    lockSkuStock.setBaseSkuid(skuStocks.getData().get(item).getSkuId());
                    lockSkuStock.setExtSkuid(skuStocks.getData().get(item).getSkuId());
                    lockSkuStock.setCompanyid(skuStocks.getData().get(item).getSkuId());
                    lockSkuStock.setPlatformid(skuStocks.getData().get(item).getSkuId());
                    lockSkuStock.setStoreid(skuStocks.getData().get(item).getSkuId());
                    lockSkuStock.setLockNum(groupCountMap.get(item));
                    lockSkuStocks.add(lockSkuStock);
                });
            }
            // 解冻商品sku库存
            goodsService.unLockSkuStock(lockSkuStocks);
            // 主单和子单都更新成功返回true
            if (updateMainOrderState && updateInfoOrderState) {
                state = true;
            } else {
                state = false;
            }
        } catch (Exception e) {
            log.error("批量取消订单异常", e);
            throw new ServiceException(CommonError.error("批量取消订单异常"));
        }
        return state;
    }

    /**
     * 退款订单
     *
     * @param param param
     * @return boolean
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean refundOrder(RefundOrderPayParam param) {

        if (param.getOrderId() != null) {

            OrderMain orderMain = orderMainService.getById(param.getOrderId());

            if (orderMain != null) {
                if (orderMain.getOrderStatus().equals(OrderMainStatusEnum.DISTRIBUTION.getCode())) {
                    throw new ServiceException(CommonError.error("订单配送中，无法进行退款操作"));
                }

                // 退款时间超过截单时间
                LocalDateTime refundTime = LocalDateTime.now();
                LocalDateTime endTime = orderMain.getCreatedTime().withHour(22).withMinute(0).withSecond(0);
                if (refundTime.isAfter(endTime)) {
                    throw new ServiceException(CommonError.error("已经超过截单时间，无法进行退款操作"));
                }

                List<OrderInfo> orderInfoList = orderInfoService.listByOrderId(orderMain.getId());

                BigDecimal amount = orderMain.getAmount().multiply(BigDecimal.valueOf(100));

                //2019.08.21 改为按支付流水主键退款
                Payorder payorder = payorderService.getById(orderInfoList.get(0).getPayOrderId());
                if (payorder == null) {
                    //支付单不存在
                    throw new ServiceException(CommonError.error("支付单不存在"));
                }

                RefundRequest refundRequest = RefundRequest.builder()
                        .merId(orderMain.getPlatformId())
                        .orderId(payorder.getPayListId())
                        .merOrderId(orderInfoList.get(0).getPayOrderId().toString())
                        .refundAmount(amount.intValue())
                        .refundDesc(param.getRefundDesc())
                        .refundNo(param.getRefundId().toString())
                        .totalAmount(amount.intValue())
                        .build();

                TreeMap<String, String> map = null;
                try {
                    map = SignUtil.objectToMap(refundRequest);
                } catch (Exception e) {
                    log.error("{}", e.getMessage());
                    throw new ServiceException(CommonError.error("退款失败,请联系客服"));
                }

                String sign = SignUtil.sign(map, SignUtil.SIGN_SECRECT_KEY);

                refundRequest.setSign(sign);

                Response<Paylist> response = paymentService.refundOrder(refundRequest);
                log.error("{}", response);
                if (!response.isSuccess()) {
                    throw new ServiceException(CommonError.error("退款失败,请联系客服"));

                }

                //修改子订单表
                if (CollectionUtils.isNotEmpty(orderInfoList)) {
                    List<LockSkuStock> lockSkuStocks = new ArrayList<>(16);
                    orderInfoList.forEach(orderInfo -> {
                        // 订单退款
                        orderInfo.setOrderStatus(OrderInfoStatusEnum.REFUND_SUCCESS.getCode())
                                // .setPayStatus(PayStatusEnum.HAS_REFUND.getCode())
                                //取消时间
                                .setCancelledTime(LocalDateTime.now())
                                //更新时间
                                .setUpdatedTime(LocalDateTime.now())
                                .setUpdatedBy("admin");

                        LockSkuStock lockSkuStock = LockSkuStock.builder()
                                // 扩展skuId
                                .extSkuid(orderInfo.getSkuId())
                                // 租户Id
                                .companyid(orderInfo.getCompanyId())
                                // 平台Id
                                .platformid(orderInfo.getPlatformId())
                                // 店铺Id
                                .storeid(orderInfo.getStoreId())
                                // 商品数量
                                .lockNum(orderInfo.getQuantity())
                                .build();
                        lockSkuStocks.add(lockSkuStock);
                    });

                    if (orderInfoService.updateBatchById(orderInfoList)) {

                        // 修改主订单订单关闭
                        OrderMain updateOrderMain = orderMain.setOrderStatus(OrderMainStatusEnum.ORDER_CLOSED.getCode())
                                // .setPayStatus(PayStatusEnum.HAS_REFUND.getCode())
                                //取消时间
                                .setCancelledTime(LocalDateTime.now())
                                //更新时间
                                .setUpdatedTime(LocalDateTime.now())
                                .setUpdatedBy("admin");
                        orderMainService.updateById(updateOrderMain);
                        //解冻商品sku库存
                        goodsService.unLockSkuStock(lockSkuStocks);
                    } else {
                        throw new ServiceException("退款失败");
                    }

                }

            }
            return true;
        } else {
            return false;
        }
    }

    /**
     * 删除订单
     *
     * @param orderId orderId
     * @return boolean
     */
    @Override
    public boolean deleteOrder(Long orderId) {
        if (null != orderId) {
            OrderMain orderMain = orderMainService.getById(orderId);
            if (null != orderMain) {
                if (OrderMainStatusEnum.ORDER_CANCELLATION.getCode()
                        .equals(orderMain.getOrderStatus())) {
                    // 已删除
                    orderMain.setDeleted(DeleteStatusEnum.DELETED.getCode())
                            .setUpdatedTime(LocalDateTime.now())
                            .updateById();

                    // orderMainService.updateById(orderMain);

                    // 修改子订单表
                    List<OrderInfo> orderInfoList = orderInfoService.listByOrderId(orderId);

                    if (CollectionUtils.isNotEmpty(orderInfoList)) {
                        for (OrderInfo orderInfo : orderInfoList) {
                            //已删除
                            orderInfo.setDeleted(DeleteStatusEnum.DELETED.getCode())
                                    //更新时间
                                    .setUpdatedTime(LocalDateTime.now())
                                    .setOrderStatus(
                                            OrderInfoStatusEnum.ORDER_CANCELLATION.getCode());
                        }
                        orderInfoService.updateBatchById(orderInfoList);
                    }
                }
            } else {
                //如果订单未取消，不能删除
                throw new ServiceException(CommonError.error("订单未取消，无法进行删除操作"));
            }

            return true;
        } else {
            return false;
        }
    }

    /**
     * 发送消息测试
     */
    @Override
    public void sendMsg(PoBillDTO poBillDTO) {
        try {
            //推送消息生成采购订单
            EncryptedResponseDTO encryptData = EncryptionUtil
                    .encryptData(poBillDTO, RsaConfig.getClientPrivateKey(), RsaConfig.getServerPublicKey());

            String data = JSON.toJSONString(encryptData);

            String base64Info = Base64.getEncoder().encodeToString(data.getBytes());

            log.info("发送生成采购订单消息:" + base64Info);

            rabbitTemplate.convertAndSend(QueueConsts.PUSH_PO_QUEUE, base64Info);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public Response<Page<OrderDTO>> listOrder(Page page, QueryWrapper<OrderMain> queryWrapper) {

        IPage<OrderMain> orderMainIPage = orderMainService.page(page, queryWrapper);

        List<OrderMain> orderMainList = orderMainIPage.getRecords();

        List<OrderDTO> orderDTOList = new ArrayList<>(10);

        if (CollectionUtils.isNotEmpty(orderMainList)) {

            orderMainList.forEach(orderMain -> {
                int count = 0;

                OrderDTO orderDTO = new OrderDTO();

                this.copyOrderMain(orderDTO, orderMain);

                List<OrderInfo> orderInfoList = orderInfoService.listByOrderId(orderMain.getId());

                List<OrderGoodsDTO> orderGoodsDTOList = null;

                if (CollectionUtils.isNotEmpty(orderInfoList)) {
                    // 现在取第一个子订单的支付单号 合并付款情况还需要另外考虑了
                    orderDTO.setPaybillNo(orderInfoList.get(0).getPayOrderId());
                    orderGoodsDTOList = new ArrayList<>(10);
                    for (OrderInfo orderInfo : orderInfoList) {

                        OrderGoodsDTO orderGoodsDTO = new OrderGoodsDTO();
                        copyOrderInfo(orderGoodsDTO, orderInfo);
                        count += orderInfo.getQuantity();

                        orderGoodsDTOList.add(orderGoodsDTO);
                    }

                }

                orderDTO.setList(orderGoodsDTOList);
                orderDTO.setGoodsCount(count);
                orderDTOList.add(orderDTO);

            });
        }

        Page<OrderDTO> pageData = new Page<>();

        BeanUtils.copyProperties(orderMainIPage, pageData);

        pageData.setRecords(orderDTOList);

        return Response.data(pageData);
    }

    @Override
    public Response<List<OrderDTO>> listAllOrders(QueryWrapper<OrderMain> queryWrapper) {
        List<OrderMain> orderMainList = orderMainService.list(queryWrapper);
        List<OrderDTO> orderDTOList = new ArrayList<>(10);
        if (CollectionUtils.isNotEmpty(orderMainList)) {

            orderMainList.forEach(orderMain -> {
                int count = 0;

                OrderDTO orderDTO = new OrderDTO();

                this.copyOrderMain(orderDTO, orderMain);

                List<OrderInfo> orderInfoList = orderInfoService.listByOrderId(orderMain.getId());

                List<OrderGoodsDTO> orderGoodsDTOList = null;

                if (CollectionUtils.isNotEmpty(orderInfoList)) {
                    // 现在取第一个子订单的支付单号 合并付款情况还需要另外考虑了
                    orderDTO.setPaybillNo(orderInfoList.get(0).getPayOrderId());
                    orderGoodsDTOList = new ArrayList<>(10);
                    for (OrderInfo orderInfo : orderInfoList) {

                        OrderGoodsDTO orderGoodsDTO = new OrderGoodsDTO();
                        copyOrderInfo(orderGoodsDTO, orderInfo);
                        count += orderInfo.getQuantity();

                        orderGoodsDTOList.add(orderGoodsDTO);
                    }

                }

                orderDTO.setList(orderGoodsDTOList);
                orderDTO.setGoodsCount(count);
                orderDTOList.add(orderDTO);

            });
        }
        return Response.data(orderDTOList);
    }

    /**
     * copy订单主单
     *
     * @param orderDTO  orderDTO
     * @param orderMain orderMain
     */
    private void copyOrderMain(OrderDTO orderDTO, OrderMain orderMain) {
//        String address = String
//                .format("%s%s%s%s", orderMain.getProvinceName(), orderMain.getCityName(),
//                        orderMain.getDistrictName(), orderMain.getAddress());
        //订单id
        orderDTO.setOrderId(orderMain.getId())
                //订单编号
                .setOrderNo(orderMain.getMainNo())
                //物流单号
                .setInvoiceNo(orderMain.getInvoiceNo())
                //是否评价
                .setCommented(orderMain.getCommented())
                //支付方式
                .setPaymentName(orderMain.getPayName())
                //付款金额
                .setPayAmount(orderMain.getAmount())
                //商品金额
                .setGoodsAmount(orderMain.getGoodsAmount())
                //优惠金额
                .setBenefitsAmount(orderMain.getBenefitsAmount())
                //收货人ID
                .setMemberId(orderMain.getMemberId())
                //收货人
                .setConsignee(orderMain.getConsignee())
                //收货人电话
                .setTelephone(orderMain.getMobile())
                //收货人地址
                .setAddress(orderMain.getAddress());

        if (orderMain.getStoreId() != null) {
            Response<PlatStoreDTO> rsp = platStoreService.getStore(orderMain.getStoreId());
            if (rsp != null) {
                PlatStoreDTO storeDTO = rsp.getData();
                // 店铺ID
                orderDTO.setStoreId(orderMain.getStoreId())
                        // 收货人地址
                        .setStoreAddress(storeDTO.getAddress())
                        // 店铺经度
                        .setStoreLongitude(storeDTO.getLongitude())
                        // 店铺名称
                        .setStoreName(storeDTO.getStoreName())
                        // 店铺维度
                        .setStoreLatitude(storeDTO.getLatitude())
                        .setStoreTelephone(
                                storeDTO.getTelphone() == null ? storeDTO.getMobile()
                                        : storeDTO.getTelphone());// 店铺电话
            }
        }
        //进口税
        orderDTO.setImportTax(BigDecimal.ZERO)
                //订单备注
                .setPostscript(orderMain.getPostscript())
                //运费
                .setShippingFee(orderMain.getShippingFee())
                //订单状态
                .setOrderStatus(orderMain.getOrderStatus())
                // 配送状态
                .setShippingStatus(orderMain.getShippingStatus())
                // 支付状态
                .setPayStatus(orderMain.getPayStatus())
                // 订单状态显示
                .setOrderCnStatus(OrderMainStatusEnum.getByCode(orderMain.getOrderStatus()).getName())
                // 售后状态
                .setServiceStatus(orderMain.getServiceStatus())
                // 售后状态显示
                .setServiceCnStatus(OrderInfoServiceStatusEnum.get(orderMain.getServiceStatus()).getName());

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

        if (orderMain.getCreatedTime() != null) {
            orderDTO.setCreateTime(orderMain.getCreatedTime().format(formatter));
        }
        if (orderMain.getDeliveryTime() != null) {
            orderDTO.setDeliveryTime(orderMain.getDeliveryTime().format(formatter));
        }
        if (orderMain.getPaidTime() != null) {
            orderDTO.setPayTime(orderMain.getPaidTime().format(formatter));
        }
        // 待核销
        if (OrderMainStatusEnum.WAIT_EXTRACT.getCode().equals(orderDTO.getOrderStatus())) {
            orderDTO.setCode(AESUtil.encrypt(orderMain.getId().toString()))
                    .setPickUpCode(orderMain.getPickUpCode());
        }

    }

    private void copyOrderInfo(OrderGoodsDTO orderGoodsDTO, OrderInfo orderInfo) {
        //商品数量
        orderGoodsDTO.setGoodsCount(orderInfo.getQuantity().intValue());
        //商品名称
        orderGoodsDTO.setGoodsName(orderInfo.getSpuName());
        //支付单号
        orderGoodsDTO.setPaybillNo(orderInfo.getPayOrderId());
        //子订单ID
        orderGoodsDTO.setId(orderInfo.getId());
        if (StringUtils.isNotEmpty(orderInfo.getSpuExtendSpec())) {

            Map<String, Object> specMap = JSON.parseObject(orderInfo.getSpuExtendSpec(), Map.class);
            Map m1 = (Map) specMap.get("spec1");
            Map m2 = (Map) specMap.get("spec2");
            Map m3 = (Map) specMap.get("spec3");

            String spec1 = "";
            String spec2 = "";
            String spec3 = "";

            if (m1 != null) {
                if (m1.get("spec_name") != null) {
                    spec1 = m1.get("spec_name").toString();
                }
            }

            if (m2 != null) {
                if (m2.get("spec_name") != null) {
                    spec1 = m2.get("spec_name").toString();
                }
            }

            if (m3 != null) {
                if (m3.get("spec_name") != null) {
                    spec1 = m3.get("spec_name").toString();
                }
            }

            String specName = String.format("%s %s %s", spec1, spec2, spec3);
            //规格名称
            orderGoodsDTO.setSpecName(specName);
        }
        //商品价格
        orderGoodsDTO.setGoodsPrice(orderInfo.getUnitPrice())
                //订单状态
                .setOrderStatus(orderInfo.getOrderStatus())
                //订单状态名
                .setOrderCnStatus(OrderInfoStatusEnum.getByCode(orderInfo.getOrderStatus()).getName())
                //售后状态
                .setServiceStatus(orderInfo.getServiceStatus())
                //售后状态名称
                .setServiceCnStatus(OrderInfoServiceStatusEnum.get(orderInfo.getServiceStatus()).getName());

        Response<ExtSkuDTO> response = goodsService.getExtSku(orderInfo.getSkuId());

        if (response != null && response.getData() != null) {
            ExtSkuDTO extSkuDTO = response.getData();
            //商品sku图片
            orderGoodsDTO.setGoodsImage(extSkuDTO.getSkuImage());
            // 取货间隔时间
            orderGoodsDTO.setReceiptInterval(extSkuDTO.getReceiptInterval());
            orderGoodsDTO.setReceiptDate(extSkuDTO.getReceiptDate());
            // 截单时间（默认为22:00）
            orderGoodsDTO.setEndTime("22:00");
        }

    }


    /**
     * 订单详情
     *
     * @param orderId orderId
     * @return Response
     */
    @Override
    public Response viewOrder(Long orderId) {
        OrderDTO orderDTO = new OrderDTO();

        OrderGoodsDTO orderGoodsDTO;
        int count = 0;
        List<OrderGoodsDTO> orderGoodsDTOList = new ArrayList<>(10);

        OrderMain orderMain = orderMainService.getById(orderId);

        copyOrderMain(orderDTO, orderMain);

        List<OrderInfo> orderInfoList = orderInfoService.listByOrderId(orderMain.getId());

        if (CollectionUtils.isNotEmpty(orderInfoList)) {
            // 现在取第一个子订单的支付单号 合并付款情况还需要另外考虑了
            orderDTO.setPaybillNo(orderInfoList.get(0).getPayOrderId());
            for (OrderInfo orderInfo : orderInfoList) {
                orderGoodsDTO = new OrderGoodsDTO();
                copyOrderInfo(orderGoodsDTO, orderInfo);
                count += orderInfo.getQuantity();
                orderGoodsDTOList.add(orderGoodsDTO);
            }
        }
        orderDTO.setList(orderGoodsDTOList)
                .setGoodsCount(count);
        return Response.data(orderDTO);
    }

    /**
     * 核销订单
     *
     * @param orderId orderId
     * @return Response
     */
    @Override
    public Response verificationOrder(Long orderId) {
        try {

            // 根据主订单id查询
            OrderMain orderMain = orderMainService.getById(orderId);

            if (OrderMainStatusEnum.SUCCESSFUL_DEAL.getCode()
                    .equals(orderMain.getOrderStatus())) {
                return Response.failed("该订单已核销");
            }

            QueryWrapper<OrderInfo> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(OrderInfo::getMainId, orderId);
            List<OrderInfo> orderInfoList = orderInfoService.listByQueryWrapper(queryWrapper);

            if (CollectionUtils.isNotEmpty(orderInfoList)) {

                List<OrderInfo> updateOrderInfoList = new ArrayList<>();
                for (OrderInfo orderInfo : orderInfoList) {
                    //修改子订单状态
                    OrderInfo updateOrderInfo = OrderInfo.builder()
                            .id(orderInfo.getId())
                            .orderStatus(OrderInfoStatusEnum.EXTRACT_GOODS.getCode())
                            // .shippingStatus()
                            .updatedTime(LocalDateTime.now())
                            .build();

                    updateOrderInfoList.add(updateOrderInfo);
                }
                orderInfoService.updateByList(updateOrderInfoList);

                //修改主订单状态及时间
                orderMain.setOrderStatus(OrderMainStatusEnum.SUCCESSFUL_DEAL.getCode())
                        // .setShippingStatus(ShippingStatusEnum.HAS_RECEIVED.getCode())
                        .setUpdatedTime(LocalDateTime.now());
                orderMainService.updateById(orderMain);
            }

        } catch (Exception e) {
            log.error("核销订单异常", e);
            throw new ServiceException(CommonError.error("核销订单失败"));

        }

        return Response.success("核销成功");
    }

    /**
     * 核销订单
     *
     * @param orderIds orderIds
     * @return Response
     */
    @Override
    public Response verificationBatchOrder(List<Long> orderIds) {
        try {

            List<OrderMain> updateOrderMainList = new ArrayList<>();
            List<OrderInfo> updateOrderInfoList = new ArrayList<>();

            for (Long orderId : orderIds) {

                // 根据主订单id查询
                OrderMain orderMain = orderMainService.getById(orderId);

                if (OrderMainStatusEnum.SUCCESSFUL_DEAL.getCode()
                        .equals(orderMain.getOrderStatus())) {
                    continue;
                }

                QueryWrapper<OrderInfo> queryWrapper = new QueryWrapper<>();
                queryWrapper.lambda().eq(OrderInfo::getMainId, orderId);
                List<OrderInfo> orderInfoList = orderInfoService.listByQueryWrapper(queryWrapper);

                if (orderInfoList.size() > 0) {

                    for (OrderInfo orderInfo : orderInfoList) {
                        //修改子订单状态
                        OrderInfo updateOrderInfo = OrderInfo.builder()
                                .id(orderInfo.getId())
                                .orderStatus(OrderInfoStatusEnum.EXTRACT_GOODS.getCode())
                                .updatedTime(LocalDateTime.now())
                                .build();

                        updateOrderInfoList.add(updateOrderInfo);
                    }

                    //修改主订单状态及时间
                    orderMain.setOrderStatus(OrderMainStatusEnum.SUCCESSFUL_DEAL.getCode())
                            .setUpdatedTime(LocalDateTime.now());
                    updateOrderMainList.add(orderMain);
                }
            }
            orderInfoService.updateByList(updateOrderInfoList);

            orderMainService.updateByList(updateOrderMainList);
        } catch (Exception e) {
            log.error("核销订单异常", e);
            throw new ServiceException(CommonError.error("核销订单失败"));

        }

        return Response.success("核销成功");
    }

    /**
     * 更新订单状态
     *
     * @param param param
     * @return Response
     */
    @Override
    public Response updateOrderStatus(OrderMainStatusUpdateParam param) {
        try {

            // 根据主订单id查询
            OrderMain orderMain = orderMainService.getById(param.getOrderId());

            if (orderMain == null) {
                return Response.failed("订单异常");
            }

            QueryWrapper<OrderInfo> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda().eq(OrderInfo::getMainId, param.getOrderId());
            List<OrderInfo> orderInfoList = orderInfoService.listByQueryWrapper(queryWrapper);

            if (CollectionUtils.isNotEmpty(orderInfoList)) {

                List<OrderInfo> updateOrderInfoList = new ArrayList<>();
                for (OrderInfo orderInfo : orderInfoList) {
                    //修改子订单状态
                    // OrderInfo updateOrderInfo = new OrderInfo();
                    //
                    OrderInfo updateOrderInfo = OrderInfo.builder().id(orderInfo.getId())
                            .orderStatus(param.getStatus())
                            // .shippingStatus(param.getStatus())
                            .updatedTime(LocalDateTime.now())
                            .build();

                    updateOrderInfoList.add(updateOrderInfo);
                }
                orderInfoService.updateBatchById(updateOrderInfoList, updateOrderInfoList.size());

                //修改主订单状态及时间
                orderMain.setOrderStatus(param.getStatus())
                        // .setShippingStatus(param.getStatus())
                        .setUpdatedTime(LocalDateTime.now());
                orderMainService.updateById(orderMain);
            }

        } catch (Exception e) {
            log.error("更新订单状态异常", e);
            throw new ServiceException(CommonError.error("更新订单失败"));

        }

        return Response.success("更新成功");
    }

    /**
     * 查询商品购买记录
     *
     * @param page         分页参数
     * @param queryWrapper 查询条件
     * @return Response<Page < Map < String, Object>>>
     */
    @Override
    public Response<Page<Map<String, Object>>> queryOrdersWithUserInfo(Page page,
            QueryWrapper<OrderInfo> queryWrapper) {
        return Response.data(orderInfoMapper.queryOrdersWithUserInfo(page, queryWrapper));
    }

    /**
     * 多条件查询订单列表
     *
     * @param page  分页对象
     * @param param param
     * @param key   key
     * @return IPage<OrderMultiConditionDTO>
     * @see #setQueryParamMap(OrderMainQueryParam, Map) 设置查询map的参数
     * @see #setOrderMultiConditionDTO(Map)  设置orderMultiConditionDTO的属性值
     */
    @Override
    // @Cacheable(cacheNames = "OrderMain", key = "#root.targetClass.simpleName+':'+#root.methodName+':'+#key")
    @Logable(authName = "销售订单-订单信息管理-多条件查询")
    public Page<OrderMultiConditionDTO> multiConditionQueryOrderPage(
            Page<OrderMultiConditionDTO> page,
            OrderMainQueryParam param, HttpServletRequest httpServletRequest, String key) {

        List<OrderMultiConditionDTO> orderMultiConditionDtoList = new ArrayList<>(10);

        TokenUsersVO userInfo = UserInfoUtil.getUserInfo(httpServletRequest);
        Long storeId = userInfo.getStoreId();
        // 查询这个店铺是否是总店
        Response<Boolean> response = platStoreService.identifyMainStoreById(storeId);

        if (Integer.valueOf(HttpStatus.OK.value()).equals(response.getCode())) {
            Boolean data = response.getData();
            if (data) {
                // 是总店
                param.setStoreId(storeId);
            } else {
                // 不是总店
                log.info("暂无订单数据");
                return page.setRecords(orderMultiConditionDtoList);
            }
        }

        Map<String, Object> paramMap = new HashMap<>(10);

        // 设置查询map的参数
        this.setQueryParamMap(param, paramMap);

        // 先查询出所有的主单Id, 然后进行组装
        List<String> orderMainIdList = orderMainMapper.multiConditionQueryOrderMainGroup(page, paramMap);
        List<String> orderMainIdPageList = orderMainMapper.multiConditionQueryOrderMainGroup(paramMap);

        // 查询每个商品的的规格名称
        if (CollectionUtils.isEmpty(orderMainIdList)) {
            // 如果没有数据直接返回
            log.error("暂无订单数据");
            return page.setRecords(orderMultiConditionDtoList);
        }

        for (String orderMainId : orderMainIdList) {
            List<Map<String, Object>> orderInfoMaps = orderMainMapper
                    .multiConditionQueryOrderByMainNo(paramMap, orderMainId);
            if (CollectionUtils.isNotEmpty(orderInfoMaps)) {
                Map<String, Object> commonalityMap = orderInfoMaps.get(0);
                // 设置orderMultiConditionDTO的属性值
                OrderMultiConditionDTO orderMultiConditionDTO = setOrderMultiConditionDTO(commonalityMap);

                orderInfoMaps.forEach(orderInfoMap -> {
                    // 设置GoodsAttributeDTO的树形
                    List<GoodsAttributeDTO> goodsAttributeDtoList = new ArrayList<>(10);
                    orderInfoMaps.forEach(privateMap -> this.setGoodsAttributeDTO(goodsAttributeDtoList, privateMap));

                    // 将商品信息加入orderMultiConditionDTO中
                    orderMultiConditionDTO.setGoodsAttributeDTO(goodsAttributeDtoList);
                });

                // 将订单列表返回回去
                orderMultiConditionDtoList.add(orderMultiConditionDTO);
            }
        }
        page.setSize(orderMultiConditionDtoList.size())
                .setTotal(orderMainIdPageList.size());

        return page.setRecords(orderMultiConditionDtoList);
    }

    /**
     * 根据主订单编号查询订单详情信息
     *
     * @param orderMainNo orderMainNo
     * @return OrderMultiConditionDTO
     */
    @Override
    @Cacheable(cacheNames = "OrderMain", key = "#root.targetClass.simpleName+':'+#root.methodName+':'+#orderMainNo")
    @Logable(authName = "销售订单-订单信息管理-订单详情信息")
    public OrderMultiConditionDTO orderDetailsQuery(String orderMainNo, String shippingId) {

        List<Map<String, Object>> orderMainMessageMaps = orderMainMapper.orderInfoDetailsQuery(orderMainNo, shippingId);

        OrderMultiConditionDTO orderMultiConditionDto;

        if (CollectionUtils.isNotEmpty(orderMainMessageMaps)) {
            LinkedList<GoodsAttributeDTO> goodsAttributeDtoList = new LinkedList<>();

            Map<String, Object> orderMainMap = orderMainMessageMaps.get(0);
            String createdTime = orderMainMap.getOrDefault("createdTime", "").toString();
            String paidTime = orderMainMap.getOrDefault("paidTime", "").toString();
            String cancelledTime = orderMainMap.getOrDefault("cancelledTime", "").toString();
            String deliveryTime = orderMainMap.getOrDefault("deliveryTime", "").toString();
            String receivedTime = orderMainMap.getOrDefault("receivedTime", "").toString();

            orderMainMap.put("createdTime", createdTime);
            orderMainMap.put("paidTime", paidTime);
            orderMainMap.put("cancelledTime", cancelledTime);
            orderMainMap.put("deliveryTime", deliveryTime);
            orderMainMap.put("receivedTime", receivedTime);

            // 将map转换为实体
            orderMultiConditionDto = BeanUtil.mapToBean(orderMainMap, OrderMultiConditionDTO.class, true);

            BigDecimal orderMainAmount = orderMultiConditionDto.getOrderMainAmount()
                    .setScale(2, RoundingMode.HALF_DOWN);
            BigDecimal mainAmount = orderMultiConditionDto.getMainAmount().setScale(2, RoundingMode.HALF_DOWN);

            BigDecimal mainBenefitsAmount = orderMultiConditionDto.getMainBenefitsAmount()
                    .setScale(2, RoundingMode.HALF_DOWN);

            BigDecimal mainBalanceAmount = orderMultiConditionDto.getMainBalanceAmount()
                    .setScale(2, RoundingMode.HALF_DOWN);

            BigDecimal mainCoinsAmount = orderMultiConditionDto.getMainCoinsAmount()
                    .setScale(2, RoundingMode.HALF_DOWN);

            BigDecimal mainPreferentialAmount = mainBenefitsAmount.add(mainBalanceAmount).add(mainCoinsAmount)
                    .setScale(2, RoundingMode.HALF_DOWN);

            orderMultiConditionDto.setOrderMainAmount(orderMainAmount)
                    .setMainAmount(mainAmount)
                    .setMainBenefitsAmount(mainBenefitsAmount)
                    .setMainPreferentialAmount(mainPreferentialAmount);

            // 商品主要信息
            orderMainMessageMaps.forEach(messageMap -> {
                GoodsAttributeDTO goodsAttributeDTO = BeanUtil.mapToBean(messageMap, GoodsAttributeDTO.class, true);
                String orderStatus = messageMap.get("orderStatus").toString();
                // TODO 改用新的状态设置
                goodsAttributeDTO.setOrderInfoStatus(orderStatus);
                String extendSpecJson = messageMap.get("extendSpec").toString();
                String goodsSkuValueStr = this.selectGoodsSkuValue(extendSpecJson);
                goodsAttributeDTO.setGoodsSkuValue(goodsSkuValueStr);
                goodsAttributeDtoList.add(goodsAttributeDTO);
            });

            orderMultiConditionDto.setGoodsAttributeDTO(goodsAttributeDtoList);
        } else {
            return null;
        }

        return orderMultiConditionDto;
    }

    @Override
    public ServletOutputStream branchOrdersExcelExport(String redisKey, HttpServletResponse response) {
        Object orderInfoExcelObj = redisTemplate.opsForValue().get(redisKey);
        if (orderInfoExcelObj instanceof String) {
            throw new ServiceException(orderInfoExcelObj.toString());
        }
        log.error("{}", "进入");
        List<Map<String, Object>> branchOrderList = (List<Map<String, Object>>) orderInfoExcelObj;
        branchOrderList.forEach(branchOrder -> {
            String receiptDate = branchOrder.get("receiptDate").toString();
            if (StrUtil.isNotBlank(receiptDate)) {
                branchOrder.put("receiptIntervalTime", receiptDate);
            }
            branchOrder.remove("receiptDate");
        });
        for (Map<String, Object> stringObjectMap : branchOrderList) {
            stringObjectMap.remove("extendSpec");
        }
        if (CollectionUtils.isNotEmpty(branchOrderList)) {

            log.error("{}", branchOrderList.size());

            ExcelWriter writer = ExcelUtil.getBigWriter();
            // TODO 支付时间
            writer.addHeaderAlias("orderMainNo", "主订单编号");
            writer.addHeaderAlias("orderInfoNo", "子订单编号");
            writer.addHeaderAlias("shippingId", "订单类型");
            writer.addHeaderAlias("orderStatus", "订单状态");
            // writer.addHeaderAlias("serviceStatus", "售后状态");
            writer.addHeaderAlias("storeCode", "店铺编码");
            writer.addHeaderAlias("storeName", "店铺名称");
            writer.addHeaderAlias("buyerNickName", "会员微信昵称");
            writer.addHeaderAlias("realName", "会员姓名");
            writer.addHeaderAlias("buyerPhone", "会员手机号");
            writer.addHeaderAlias("consignee", "收货人姓名");
            writer.addHeaderAlias("orderMainStoreAddress", "自提店铺地址");
            writer.addHeaderAlias("orderMainMobile", "自提人的手机号码");
            writer.addHeaderAlias("orderInfoSpuName", "商品的SPU名称");
            writer.addHeaderAlias("orderInfoSkuName", "商品的SKU名称");
            writer.addHeaderAlias("brandChineseName", "品牌中文名");
            writer.addHeaderAlias("brandEnglishName", "品牌英文名");
            writer.addHeaderAlias("orderInfoUnitPrice", "单价");
            writer.addHeaderAlias("orderInfoQuantity", "购买数量");
            writer.addHeaderAlias("createdTime", "下单时间");
            writer.addHeaderAlias("orderInfoPaidTime", "支付时间");
            writer.addHeaderAlias("receivedTime", "提货时间");
            writer.addHeaderAlias("receiptInterval", "预计发货时间T+?");
            writer.addHeaderAlias("receiptIntervalTime", "预计发货时间");
            writer.addHeaderAlias("receiptDate", "活动提货时间");
            writer.addHeaderAlias("orderAmount", "买家应付金额");
            writer.addHeaderAlias("amount", "订单实付金额");
            writer.addHeaderAlias("orderInfoSaleUnitPrice", "销售价");
            writer.addHeaderAlias("costPrice", "采购价");
            writer.addHeaderAlias("unitprice", "成本价");
            writer.addHeaderAlias("shippingFee", "配送费用");
            writer.addHeaderAlias("insureFee", "保价费用");
            writer.addHeaderAlias("payFee", "支付费用");
            writer.addHeaderAlias("packFee", "包装费用");
            writer.addHeaderAlias("tax", "发票税额");
            writer.addHeaderAlias("backAmount", "退款金额");
            writer.addHeaderAlias("coinsAmount", "金币金额");
            writer.addHeaderAlias("benefitsAmount", "优惠券金额");
            writer.addHeaderAlias("balanceAmount", "余额抵扣金额");
            writer.addHeaderAlias("payOrderNo", "支付流水号");
            writer.addHeaderAlias("payAmount", "支付单金额");
            writer.addHeaderAlias("totalPrice", "总价");
            writer.addHeaderAlias("points", "积分数");
            writer.addHeaderAlias("goodsSkuNo", "商品编号");
            writer.addHeaderAlias("goodsBarCode", "商品条形码");
            writer.addHeaderAlias("packetUnit", "包装单位");
            // writer.addHeaderAlias("goodsSkuValue", "规格值");
            // writer.addHeaderAlias("goodsCategory", "品牌信息");
            writer.setColumnWidth(-1, 20);
            // 合并单元格后的标题行，使用默认标题样式
            writer.write(branchOrderList, true);

            response.setContentType("application/vnd.ms-excel;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=test.xlsx");
            ServletOutputStream out = null;
            try {
                out = response.getOutputStream();
            } catch (IOException e) {
                throw new ServiceException("转换失败");
            }
            // 关闭writer，释放内存
            writer.flush(out);
            writer.close();
            IoUtil.close(out);
            return out;
        }

        throw new ServiceException("没有数据");
    }

    @Override
    @Async
    public void getExportRedisKey(BranchOrderQueryParam branchOrderQueryParam,
            HttpServletRequest httpServletRequest, String redisKey) {

        List<Map<String, Object>> branchOrderList;
        branchOrderList = this
                .selectExportExcelMessage(branchOrderQueryParam, httpServletRequest, redisKey);

        if (CollectionUtils.isEmpty(branchOrderList)) {
            redisTemplate.opsForValue().set(redisKey, "该条件下没有数据, 无法导出", 2, TimeUnit.SECONDS);
            return;
        }
        if (CollectionUtils.isNotEmpty(branchOrderList)) {
            redisTemplate.opsForValue().set(redisKey, branchOrderList, 10, TimeUnit.SECONDS);
        }
    }

    @Override
    public Page multiConditionBranchOrders(BranchOrderQueryParam branchOrderQueryParam, Page page,
            HttpServletRequest httpServletRequest) {
        // 这里需要查询出他的父级ID
        if (null != branchOrderQueryParam.getOrderMainNo()) {
            branchOrderQueryParam.setOrderMainNo(branchOrderQueryParam.getOrderMainNo().trim());
        }

        String ipAddress = IpUtils.getIpAddress(httpServletRequest);

        Map<String, Object> branchOrderQueryParamMap = BeanUtil.beanToMap(branchOrderQueryParam, false, true);

        this.setOrderInfoStoreWrapper(branchOrderQueryParam, httpServletRequest, branchOrderQueryParamMap, ipAddress);

        List<Map<String, Object>> branchOrderList = orderInfoService
                .multiConditionBranchOrders(branchOrderQueryParamMap, page);

        List<Map<String, Object>> branchOrderAllList = orderInfoService
                .multiConditionBranchOrders(branchOrderQueryParamMap);

        for (Map<String, Object> branchOrder : branchOrderList) {
            // json字符串
            this.setReturnMapMessage(branchOrder);
        }
        log.error("{}", branchOrderAllList.size());

        page.setRecords(branchOrderList);
        page.setSize(branchOrderList.size());
        page.setTotal(branchOrderAllList.size());
        return page;
    }

    private void setOrderInfoStoreWrapper(BranchOrderQueryParam branchOrderQueryParam,
            HttpServletRequest httpServletRequest, Map<String, Object> branchOrderQueryParamMap, String redisKey) {
        if (branchOrderQueryParam.getPlatStoreId() == null) {
            TokenUsersVO userInfo = null;
            try {
                userInfo = UserInfoUtil.getUserInfo(httpServletRequest);
            } catch (Exception e) {
                redisTemplate.opsForValue().set(redisKey, "导出订单异常, 请重新登录重试", 2, TimeUnit.SECONDS);
                return;
            }
            Long storeId = null;
            if (null == userInfo) {
                redisTemplate.opsForValue().set(redisKey, "导出订单异常, 获取不到用户信息", 2, TimeUnit.SECONDS);
                return;
            } else {
                storeId = userInfo.getStoreId();
            }

            if (null == storeId) {
                redisTemplate.opsForValue().set(redisKey, "导出订单异常, 获取不到店铺ID", 2, TimeUnit.SECONDS);
                return;
            }

            // 得到所有的子店
            Response<List<PlatStore>> response = platStoreService.getAllBranchStore(storeId);
            if (Integer.valueOf(HttpStatus.OK.value()).equals(response.getCode())) {
                List<PlatStore> platStoreList = response.getData();
                if (CollectionUtils.isNotEmpty(platStoreList)) {
                    String storeIdArrStr = StringUtils
                            .join(platStoreList.stream().map(PlatStore::getId).toArray(), " OR oi.store_id = ");
                    branchOrderQueryParamMap.put("storeIdArrStr", storeIdArrStr);
                }
            } else {
                redisTemplate.opsForValue().set(redisKey, "导出订单异常, 查询分店异常", 2, TimeUnit.SECONDS);
                return;
            }
        }
    }

    @Override
    public boolean getRedisHasKey(String key) {
        if (StrUtil.isBlank(key)) {
            redisTemplate.opsForValue().set(key, "key丢失,请重试", 2, TimeUnit.SECONDS);
            return false;
        }
        Boolean hasKeyBoolean = redisTemplate.hasKey(key);
        if (Boolean.TRUE.equals(hasKeyBoolean)) {
            Object excelMessageObjStr = redisTemplate.opsForValue().get(key);
            if (excelMessageObjStr instanceof String) {
                log.error(excelMessageObjStr.toString());
                throw new ServiceException(excelMessageObjStr.toString());
            }
        }

        return hasKeyBoolean;
    }

    @Override
    public List<Map<String, Object>> getOrderInfoAllMessage(BranchOrderQueryParam branchOrderQueryParam) {
        return this.getOrderInfoMessage(branchOrderQueryParam);
    }

    /**
     * 添加出货单
     *
     * @param dispatchBillAndDetailDTO dispatchBillAndDetailDTO
     * @param httpServletRequest       httpServletRequest
     * @see #setDispatchBillMessage(Response, TokenUsersVO, String, LocalDateTime) 设置DisPatchBill的值
     * @see #addDispatchBillDeailListAndMessage(TokenUsersVO, String, List, LocalDateTime, Long) 设置DispatchBill详情的值
     * @see #setIdType(Integer, Set) 将ID转换为Long类型
     * @see #setDispatchBillDetailsInsert(Map, Iterator) 设置插入集合
     */
    @Override
    @CacheEvict(cacheNames = "DispatchBill", allEntries = true)
    public void addDispatchBill(DispatchBillAndDetailDTO dispatchBillAndDetailDTO,
            HttpServletRequest httpServletRequest) {

        TokenUsersVO userInfo = UserInfoUtil.getUserInfo(httpServletRequest);

        Response<Boolean> identifyMainResponse = platStoreService.identifyMainStoreById(userInfo.getStoreId());
        if (!Integer.valueOf(HttpStatus.OK.value()).equals(identifyMainResponse.getCode())) {
            throw new ServiceException("查询店铺平台失败");
        }
        if (!identifyMainResponse.getData()) {
            throw new ServiceException("您不是总店人员, 无法添加发货单");
        }

        Long storeId = dispatchBillAndDetailDTO.getStoreId();

        Response<PlatDTO> responsePlatDto = platStoreService.getStoreAndFormByStoreId(storeId);

        if (!Integer.valueOf(HttpStatus.OK.value()).equals(responsePlatDto.getCode())) {
            throw new ServiceException("查询店铺平台失败");
        }
        String remark = "这是 " + dispatchBillAndDetailDTO.getCreatedOrderStartTime() + " 到"
                + dispatchBillAndDetailDTO.getCreatedOrderEndTime() + " 下单的";

        // 从子单表里面查询出, 对应的发货单
        List<Map<String, Object>> dispatchBillDetailMapList = orderInfoMapper
                .selectDispatchBillDetail(dispatchBillAndDetailDTO);

        if (dispatchBillDetailMapList.isEmpty()) {
            throw new ServiceException("该条件下没有订单, 无法生成出库单");
        }

        // 直接可以插入DispatchBill单
        LocalDateTime now = LocalDateTime.now();
        DispatchBill dispatchBill = this.setDispatchBillMessage(responsePlatDto, userInfo, remark, now);
        Long dispatchBillId = dispatchBill.getId();

        // 将数据转换并设置值添加到dispatchBillDetailList中
        List<DispatchBillDetail> dispatchBillDetailList = this.addDispatchBillDeailListAndMessage(userInfo, remark,
                dispatchBillDetailMapList, now, dispatchBillId);

        // 计算改出货单有多少个商品 Start
        long sum = dispatchBillDetailList.stream().mapToLong(DispatchBillDetail::getQuantity).sum();
        dispatchBill.setQuantity(sum);
        // 查询订单信息, 查询这个店铺下面的所有的订单
        boolean dispatchBillInsert = dispatchBill.insert();

        if (!dispatchBillInsert) {
            throw new ServiceException("新增出过单失败");
        }
        // 计算该出货单有多少个商品 End

        Map<Long, List<DispatchBillDetail>> dispatchBillDetailGroupList = dispatchBillDetailList.stream()
                .collect(Collectors.groupingBy(DispatchBillDetail::getSkuId));

        int size = dispatchBillDetailGroupList.size();
        Set<String> idStrSet = idGeneratorService.queryGeneratorIds(size);
        Set<Long> dispatchBillDetailIdSet = this.setIdType(size, idStrSet);
        Iterator<Long> dispatchBillDetailIterator = dispatchBillDetailIdSet.iterator();

        List<DispatchBillDetail> dispatchBillDetailsInsert = this.setDispatchBillDetailsInsert(
                dispatchBillDetailGroupList, dispatchBillDetailIterator);

        // 插入成功
        try {
            dispatchBillDetailService.saveBatch(dispatchBillDetailsInsert);
        } catch (Exception e) {
            throw new ServiceException("添加发货单失败, 批量添加发货单详情有误");
        }
    }

    /**
     * 将数据从dispatchBillDetailGroupList 取出处理后, 添加到集合中, 准备批量操作
     *
     * @param dispatchBillDetailGroupList dispatchBillDetailGroupList
     * @param dispatchBillDetailIterator  dispatchBillDetailIterator
     * @return ArrayList
     */
    private List<DispatchBillDetail> setDispatchBillDetailsInsert(
            Map<Long, List<DispatchBillDetail>> dispatchBillDetailGroupList,
            Iterator<Long> dispatchBillDetailIterator) {
        ArrayList<DispatchBillDetail> dispatchBillDetailsInsert = new ArrayList<>(10);
        dispatchBillDetailGroupList.forEach((key, dispatchBillDetails) -> {

            Long quantitySum = dispatchBillDetails.stream().mapToLong(DispatchBillDetail::getQuantity).sum();

            DispatchBillDetail dispatchBillDetail = dispatchBillDetails.get(0);
            String spuExtendSpec = dispatchBillDetail.getSpuSpec();
            String categoryDescribe = dispatchBillDetail.getSpuCategory();
            // 商品规格
            String spec = this.selectGoodsSkuValue(spuExtendSpec);
            // 商品类目
            String brandContext = this.getBrandContext(categoryDescribe);

            if (StrUtil.isBlank(dispatchBillDetail.getSpuBarcode())) {
                dispatchBillDetail.setSpuBarcode("");
            }

            dispatchBillDetail.setId(dispatchBillDetailIterator.next())
                    .setSpuSpec(spec)
                    .setSpuCategory(brandContext)
                    .setQuantity(quantitySum);
            dispatchBillDetailsInsert.add(dispatchBillDetail);
        });
        return dispatchBillDetailsInsert;
    }

    /**
     * 将数据添加到集合中, 并设置值返回
     *
     * @param userInfo                  userInfo
     * @param remark                    remark
     * @param dispatchBillDetailMapList dispatchBillDetailMapList
     * @param now                       now
     * @param dispatchBillId            dispatchBillId
     * @return List
     */
    private List<DispatchBillDetail> addDispatchBillDeailListAndMessage(TokenUsersVO userInfo, String remark,
            List<Map<String, Object>> dispatchBillDetailMapList, LocalDateTime now, Long dispatchBillId) {
        List<DispatchBillDetail> dispatchBillDetailList = new ArrayList<>(10);
        dispatchBillDetailMapList.forEach(dispatchBillMap -> {
            // 解析json
            String spuExtendSpec = dispatchBillMap.getOrDefault("spuExtendSpec", "").toString();
            // 查询类目
            String categoryDescribe = dispatchBillMap.getOrDefault("categoryDescribe", "").toString();

            DispatchBillDetail dispatchBillDetail = BeanUtil
                    .mapToBean(dispatchBillMap, DispatchBillDetail.class, false);
            dispatchBillDetail.setDispatchBillId(dispatchBillId)
                    // 这里是故意的
                    .setSpuSpec(spuExtendSpec)
                    .setSpuCategory(categoryDescribe)
                    .setRemark(remark)
                    .setCreatedBy(userInfo.getRealName())
                    .setCreatedTime(now)
                    .setUpdatedBy(userInfo.getRealName())
                    .setUpdatedTime(now);
            dispatchBillDetailList.add(dispatchBillDetail);
        });
        return dispatchBillDetailList;
    }

    /**
     * 设置setDisPatchBill的值
     *
     * @param responsePlatDto responsePlatDto
     * @param userInfo        userInfo
     * @param remark          remark
     * @param now             now
     * @return DispatchBill
     */
    private DispatchBill setDispatchBillMessage(
            Response<PlatDTO> responsePlatDto, TokenUsersVO userInfo, String remark, LocalDateTime now) {
        String dispatchBillIdStr = idGeneratorService.queryGeneratorId();
        Long dispatchBillId = Long.valueOf(dispatchBillIdStr);
        PlatDTO platDTO = responsePlatDto.getData();
        Platform platform = platDTO.getPlatform();
        PlatStore platStore = platDTO.getPlatStore();
        Long parentId = platStore.getParentId();
        Response<PlatStoreDTO> storeResponse = platStoreService.getStore(parentId);
        if (!Integer.valueOf(HttpStatus.OK.value()).equals(responsePlatDto.getCode())) {
            throw new ServiceException("查询总店店铺失败");
        }
        PlatStoreDTO platStoreDto = storeResponse.getData();

        int nano = now.getNano();
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
        String format = now.format(dtf);
        return DispatchBill.builder()
                .id(dispatchBillId)
                .companyId(platform.getCompanyId())
                .platformId(platform.getId())
                .storeId(platStore.getId())
                .billNo(format + nano)
                .storeName(platStore.getStoreName()) // 店铺名称
                .consignee(platStore.getCharge())  // 负责人的名字等于收货人的姓名
                .consigneeTelephone(
                        platStore.getChargeTelphone() == null ? "" : platStore.getChargeTelphone()) // 负责人的电话
                .consigneeAddress(platStore.getAddress() == null ? "" : platStore.getAddress()) // 收货的地址就是店铺的地址
                .deliverer(platStoreDto.getCharge())  // 总店负责人
                .deliveryTime(now)
                .actualDeliverer(platStoreDto.getCharge()) // 实际发货人
                .createdBy(userInfo.getRealName()) // 创建人, 就是登陆人
                .createdTime(now)
                .updatedTime(now)
                .deleted(0)
                .remark(remark)
                .status(0).build();
    }


    /**
     * 设置查询map的参数
     *
     * @param param    查询实体
     * @param paramMap 条件map
     */
    private void setQueryParamMap(OrderMainQueryParam param, Map<String, Object> paramMap) {
        paramMap.put("mainNo", param.getMainNo());
        if (null == param.getShippingId()) {
            throw new ServiceException("请确认配送方式");
        } else {
            if (StrUtil.isBlank(param.getShippingId().toString())) {
                throw new ServiceException("请确认配送方式");
            }
        }
        if (null == param.getOrderStatus()) {
            throw new ServiceException("请确认订单状态");
        } else {
            if (StrUtil.isBlank(param.getOrderStatus().toString())) {
                throw new ServiceException("请确认订单状态");
            }
        }

        String status = param.getOrderStatus().toString();

        if (StrUtil.isBlank(status)) {
            throw new ServiceException("请传入订单状态");
        }

        paramMap.put("shippingId", param.getShippingId());
        paramMap.put("createdStartTime", param.getCreatedStartTime());
        paramMap.put("createdEndTime", param.getCreatedEndTime());
        paramMap.put("orderMainStatus", param.getOrderStatus().toString());
        paramMap.put("buyerPhone", param.getMobile());
        paramMap.put("buyerNickName", param.getNickName().trim());
    }

    /**
     * 设置OrderMultiConditionDTO的信息
     *
     * @param commonalityMap commonalityMap
     * @return OrderMultiConditionDTO
     */
    private OrderMultiConditionDTO setOrderMultiConditionDTO(Map<String, Object> commonalityMap) {

        return OrderMultiConditionDTO
                .builder()
                .orderMainId(Long.valueOf(commonalityMap.get("orderMainId").toString()))
                .orderMainNo(commonalityMap.getOrDefault("orderMainNo", "").toString())
                .createdTime(commonalityMap.getOrDefault("createdTime", "").toString())
                .buyerNickName(commonalityMap.getOrDefault("buyerNickName", "").toString())
                .buyerPhone(commonalityMap.getOrDefault("buyerPhone", "").toString())
                .goodsAmount(BigDecimal
                        .valueOf(Double.parseDouble(
                                commonalityMap.getOrDefault("goodsAmount", BigDecimal.ZERO).toString()))
                        .setScale(2, RoundingMode.HALF_UP))
                .settlement(Integer.valueOf(commonalityMap.getOrDefault("settlement", "0").toString()))
                .orderMainStatus(commonalityMap.get("orderMainStatus").toString())
                .commented(Integer.valueOf(commonalityMap.getOrDefault("commented", "0").toString()))
                .build();
    }

    /**
     * 设置GoodsAttributeDTO的属性
     *
     * @param goodsAttributeDtoList goodsAttributeDTOList
     * @param privateMap            privateMap
     */
    private void setGoodsAttributeDTO(List<GoodsAttributeDTO> goodsAttributeDtoList,
            Map<String, Object> privateMap) {
        // json字符串
        String extendSpecJson = privateMap.get("extendSpec").toString();
        String goodsSkuValueStr = this.selectGoodsSkuValue(extendSpecJson);

        String quantity = privateMap.getOrDefault("quantity", "").toString();
        GoodsAttributeDTO goodsAttributeDTO = GoodsAttributeDTO.builder()
                // 商品主图
                .goodsImage(privateMap.getOrDefault("goodsImage", "").toString())
                // 商品名称
                .goodsSpuName(privateMap.getOrDefault("goodsSpuName", "").toString())
                // 商品SKU名称
                .goodsSpuName(privateMap.getOrDefault("goodsSkuName", "").toString())
                // 商品的规格值字符串
                .goodsSkuValue(goodsSkuValueStr)
                // 商品的数量
                .quantity(Integer.valueOf("".equals(quantity) ? "0" : quantity))
                // 商品的单价
                .saleUnitPrice(BigDecimal.valueOf(
                        Double.parseDouble(privateMap.getOrDefault("saleUnitPrice", BigDecimal.ZERO).toString()))
                        .setScale(2, RoundingMode.HALF_UP))
                .build();
        goodsAttributeDtoList.add(goodsAttributeDTO);
    }

    /**
     * 解析extendSpec
     *
     * @param extendSpecJsonStr extendSpecJsonStr
     * @return 规格值 例子: 规格值1, 规格值2, 规格值3
     */
    private String selectGoodsSkuValue(String extendSpecJsonStr) {

        JSONObject extendSpecJsonObj = JSON.parseObject(extendSpecJsonStr);
        JSONObject spec1JsonObj;
        if (null != extendSpecJsonObj) {
            spec1JsonObj = extendSpecJsonObj.getJSONObject("spec1");
            String specId = spec1JsonObj.getString("spec_id");
            // 根据specId和specItemId查询

            Response<List<GoodsSpecificationsValues>> response = goodsService
                    .getSpecificationsValueToNameListBySpecId(Long.parseLong(specId));
            if (null != response) {
                List<GoodsSpecificationsValues> data = response.getData();
                if (CollectionUtils.isNotEmpty(data)) {

                    List<String> specNameList = data.stream()
                            .map(goodsSpecificationsValues -> {
                                GoodsSpecificationsValues goodsSpecificationsValues1;
                                if (null == goodsSpecificationsValues) {
                                    goodsSpecificationsValues1 = new GoodsSpecificationsValues();
                                    goodsSpecificationsValues1.setName("默认");
                                    return goodsSpecificationsValues1.getName();
                                }

                                // log.error("{}", goodsSpecificationsValues.getName());
                                return goodsSpecificationsValues.getName();
                            })
                            .collect(Collectors.toList());

                    return String.join(">", specNameList);
                }
            }
        }

        return "";
    }

    /**
     * 设置分店订单返回实体
     *
     * @param branchOrder branchOrder 结果map
     */
    private void setReturnMapMessage(Map<String, Object> branchOrder) {
        // json字符串
        Object extendSpecJson = branchOrder.get("extendSpec");

        // TODO 因为那边没有字段暂时这样写, 以后统一categoryContext字段
        Object categoryDescribe = branchOrder.get("categoryDescribe");
        String categoryDescribeQueryStr = "";
        String brandContext = "";
        if (null != categoryDescribe) {
            categoryDescribeQueryStr = branchOrder.get("categoryDescribe").toString();
            if (StrUtil.isNotBlank(categoryDescribeQueryStr)) {
                brandContext = this.getBrandContext(categoryDescribeQueryStr);
            }
        }

        // json字符串
        String goodsSkuValueStr = "";
        goodsSkuValueStr = this.selectGoodsSkuValue(extendSpecJson.toString());
        if (StrUtil.isNotBlank(goodsSkuValueStr)) {
            branchOrder.put("goodsSkuValue", goodsSkuValueStr);
            branchOrder.put("goodsCategory", brandContext);
        } else {
            branchOrder.put("goodsSkuValue", "");
        }

    }

    /**
     * 得到品牌内容
     *
     * @param categoryId
     * @return
     */
    private String getBrandContext(String categoryId) {
        String cateGoryName;
        String[] split = categoryId.split(",");
        String categoryNameStrArr = String.join("\',\'", split);
        String categoryNameQueryStr = "\'" + categoryNameStrArr + "\'";

        // 从缓存中获取
        String categoryNameStr = orderInfoService.selectBaseSpuCategoryId(categoryNameQueryStr);

        if (categoryNameStr != null) {
            cateGoryName = categoryNameStr.replace(",", ">");
            return cateGoryName;
        }

        return "";
    }

    /**
     * 得到所有的分店订单信息
     *
     * @param branchOrderQueryParam branchOrderQueryParam
     * @return List
     */
    private List<Map<String, Object>> selectExportExcelMessage(BranchOrderQueryParam branchOrderQueryParam,
            HttpServletRequest httpServletRequest, String redisKey) {
        log.info("{}", branchOrderQueryParam);
        // 这里需要根据3级id查询出, 他的负极id
        if (null != branchOrderQueryParam.getOrderMainNo()) {
            branchOrderQueryParam.setOrderMainNo(branchOrderQueryParam.getOrderMainNo().trim());
        }

        Map<String, Object> branchOrderQueryParamMap = BeanUtil.beanToMap(branchOrderQueryParam, false, true);

        this.setOrderInfoStoreWrapper(branchOrderQueryParam, httpServletRequest, branchOrderQueryParamMap, redisKey);

        List<Map<String, Object>> branchOrderList = orderInfoMapper
                .selectExportExcelMessage(branchOrderQueryParamMap);

        for (Map<String, Object> branchOrder : branchOrderList) {
            // json字符串
            this.setReturnMapMessage(branchOrder);
        }

        log.info("{}", branchOrderList.size());

        return branchOrderList;
    }

    /**
     * 得到所有的分店订单信息
     *
     * @param branchOrderQueryParam branchOrderQueryParam
     * @return List
     */
    private List<Map<String, Object>> getOrderInfoMessage(BranchOrderQueryParam branchOrderQueryParam) {

        // 这里需要根据3级id查询出, 他的负极id
        if (null != branchOrderQueryParam.getOrderMainNo()) {
            branchOrderQueryParam.setOrderMainNo(branchOrderQueryParam.getOrderMainNo().trim());
        }

        Map<String, Object> branchOrderQueryParamMap = BeanUtil.beanToMap(branchOrderQueryParam, false, true);

        String orderInfoStatusStr = branchOrderQueryParamMap.getOrDefault("orderInfoStatus", "").toString();

        if (StrUtil.isBlank(orderInfoStatusStr)) {
            throw new ServiceException("请传入订单状态");
        }

        List<Map<String, Object>> branchOrderList = orderInfoService
                .multiConditionBranchOrders(branchOrderQueryParamMap);

        for (Map<String, Object> branchOrder : branchOrderList) {
            // json字符串
            this.setReturnMapMessage(branchOrder);
        }
        log.error("{}", branchOrderList.size());

        return branchOrderList;
    }
}
